AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Memorystream vs TMemoryStream

Ein Thema von EWeiss · begonnen am 16. Apr 2015 · letzter Beitrag vom 18. Apr 2015
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.640 Beiträge
 
#11

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 12:45
Uh. Es ist nahezu ein Ding der Unmöglichkeit, ein Struct in .NET so zu layouten, das die Datenstruktur so aussieht, wie sie bei Delphi aussieht.

Insbesondere, wenn Du hier Strings (die sind komplett inkompatibel, weil die in .NET immer immutable Objekte sind) und eben größere Binärdaten hin- und herschieben willst.

Nur ein Beispiel: In .NET ist ein String ein Objekt, und die Daten werden geshared. Will heissen, wenn Du 15 Strings hast, und 13 davon identischen Inhalt haben, hast Du im Endeffekt 15 Objekte (also eine Komplexe Datenstruktur), und 13 davon haben intern irgendwo einen Pointer auf den selben Datenbereich mit dem Inhalt des Strings und 2 zeigen woanders hin. Wenn Du den Inhalt eines der 13 Strings jetzt änderst, dann wird geschaut, ob es den Inhalt schonmal gibt, wenn ja, wird einfach nur der Pointer verbogen, wenn nein, wird der Inhalt halt irgendwo neu angelegt und dann der Zeiger darauf hin verbogen. Das .NET Managed ist, bekommst Du ohne ganz hartes natives Debugging auch nicht raus, an welcher Speicherstelle der String jetzt eigentlich wirklich liegt.

Das, was Du machen willst, involviert sehr viel unsafe Code.

Ich würde ernsthaft vorschlagen, die Herangehensweise zu überdenken. Es wäre besser, die ganze Funktionalität in einer komplett nativen Delphi-DLL zu verpacken, nur die Methoden zu exposen, und ausschliesslich primitive Datentypen zwischendrin auszutauschen. Oder, Du nimmst sowas wie Hydra, das Dir dann wirklich erlaubt komplette Interfaces zwischen .NET und Delphi hin- und her zu schieben, und das ganze Plugin-Framework kümmert sich für Dich dann um das ganze richtige Konvertieren etc.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#12

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 12:47
So wie im Bild ersichtlich kommt auf der Delphi Seite nur Müll an.
Bin wohl damit überfordert
ist doch logisch.. das Objektmodell von Delphi entspricht halt nicht dem von .NET. Jemand der sich damit auskennt kann dir das erklären wo die Unterschiede in der Speicherverwaltung von Delphi und .net liegen (wo sind virtuelle Methoden definiert, wo die Eigenschaften....) wenn das nicht zusammen passt, dann kann bei der Interpretation auch nur Müll raus kommen.

Lösung:
Das Objekt/Record in eine XML-Datei speichern, das Bitmap dazu (mime), ggf. zippen und die komplette XML dann ins MMF. Das kannst Du dann mit jeder bel. Programmiersprache auswerten, die MMF unterstützt...

Nachtrag: Die Größe des MMF kannst Du dann per Windows-Message "herum reichen" auf die dann das andere Programm reagieren kann - das weiß dann ab wann die Infos komplett bereit stehen und auch wie groß die MMF ist in der die Daten stehen...


Grüße
Das macht keinen Sinn sorry.
Ich habe selbst eine DLL in Delphi geschrieben und einen Wrapper dazu.
Bei mir ist es nur so das ich weis welche Dateien bzw. DataTypen in Delphi deklariert werden müssen
damit eine Zusammenarbeit beider Sprachen ohne große Probleme funktioniert.

Aber wie gesagt darauf habe ich kleinen Einfluss was oder wie er seine Daten verwaltet/übergibt.
Zudem macht es absolut keinen sinn irgendetwas in ZIP Dateien zu packen denn ich lese den TAG einer X-Beliebigen MP3 Datei aus
und die Bilddatei ist im Tag enthalten.
Soll ich das dann zippen ?

gruss

Geändert von EWeiss (17. Apr 2015 um 12:52 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#13

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 12:50
Zitat:
Ich würde ernsthaft vorschlagen, die Herangehensweise zu überdenken. Es wäre besser, die ganze Funktionalität in einer komplett nativen Delphi-DLL zu verpacken, nur die Methoden zu exposen, und ausschliesslich primitive Datentypen zwischendrin auszutauschen. Oder, Du nimmst sowas wie Hydra, das Dir dann wirklich erlaubt komplette Interfaces zwischen .NET und Delphi hin- und her zu schieben, und das ganze Plugin-Framework kümmert sich für Dich dann um das ganze richtige Konvertieren etc.
Würde ich gerne machen wenn es denn meine DLL wäre.
NA ja die Strings hab ich nach IntPtr gecastet das ist kein Problem.
Das ich mit Strings keine Probleme habe kannst du sehen siehe Anhang.

Delphi-Quellcode:
type
    TCoverArtData = packed record
        Name: PWideChar;
        Data: Pointer;
        DataSize: Int64;
        Description: PWideChar;
        CoverType: DWord;
        MIMEType: PWideChar;
        PictureFormat: TTagPictureFormat;
        Width: DWord;
        Height: DWord;
        ColorDepth: DWord;
        NoOfColors: DWord;
        ID3v2TextEncoding: Integer;
        Index: Integer;
    end;
Code:
  [Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
  public sealed class TCoverArtData
  {
    private IntPtr NameSPtr;
    public IntPtr Data;
    public long DataSize;
    private IntPtr DescriptionSPtr;
    public int CoverType;
    private IntPtr MIMETypeSPtr;
    public TTagPictureFormat PictureFormat;
    public int Width;
    public int Height;
    public int ColorDepth;
    public int NoOfColors;
    public int ID3v2TextEncoding;
    public int Index;

    public string Name
    {
      get
      {
        if (NameSPtr == IntPtr.Zero)
          return null;
        else
          return Marshal.PtrToStringAuto(NameSPtr);      
      }

      set
      { 
        NameSPtr = Marshal.StringToHGlobalAuto(value);
      }
    }

    public string Description
    {
      get
      {
        if (DescriptionSPtr == IntPtr.Zero)
          return null;
        else
          return Marshal.PtrToStringAuto(DescriptionSPtr);
      }

      set
      { 
        DescriptionSPtr = Marshal.StringToHGlobalAuto(value);
      }

    }

    public string MIMEType
    {
      get
      {
        if (MIMETypeSPtr == IntPtr.Zero)
          return null;
        else
          return Marshal.PtrToStringAuto(MIMETypeSPtr);
      }
      set
      { 
        MIMETypeSPtr = Marshal.StringToHGlobalAuto(value);
      }
    }

  }
gruss

Geändert von EWeiss (11. Jul 2019 um 16:43 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.640 Beiträge
 
#14

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 12:59
Das macht keinen Sinn sorry.

Ich habe selbst eine DLL in Delphi geschrieben und einen Wrapper dazu.
Bei mir ist es nur das das ich weis welche Dateien bzw. DataTypen in Delphi deklariert werden müssen
damit eine Zusammenarbeit beider Sprachen ohne große Probleme zurechtkommen.

Aber wie gesagt darauf habe ich kleinen Einfluss was oder wie er seine Daten verwaltet/übergibt.
Das macht keinen Sinn. Sorry.

Du sagst uns nicht, was Du genau machen willst bzw. musst.

Du sagst uns nicht, welcher Teil genau in Delphi ist und welcher genau in C#. Aktuell sieht es (zumindest für mich) NICHT danach aus, das Du eine DLL ansprechen willst. Es sieht für mich danach aus, als ob Du ein Stück Delphi-Code 1:1 nach C# portieren = duplizieren willst. Inklusive UI. Das hat mit Bibliotheken/DLL (einmal geschriebener Code, der eben nicht für andere Plattformen kopiert werden muss) ehrlich gesagt genau gar nichts zu tun.

Du sagst uns nicht, was der Delphi-Code machen soll, wie das Interface Deiner Delphi-DLL aussieht die Du vielleicht(? - siehe vorherigen Absatz) aus .NET ansprechen willst.

Du sagst uns auch nicht, wer der andere ist, der seine Daten (welche?) verwaltet und übergibt. Auch das ist für mich gerade Sinnbefreit, denn wenn Du eine DLL bereit stellst, definierst Du damit da genau die Schnittstelle, über die jemand anderes Daten an Dich übergibt. Eigentlich hast Du damit die 100%ige Kontrolle darüber, wie jemand seine Daten an Dich zu übergeben hat.

Ich kenne Deine Systeme und die Systemgrenzen nicht. Ich sehe doppelten udn nicht mehrfach verwendeten Code, und ich sehe das Du da zwei Plattformen hast, deren interne Datenstrukturen die Du direkt übergeben willst (sinnlos) grundlegend inkompatibel sind.

Sorry, aber um da wirklich Zielführend zu helfen brauch ich echt viel mehr Informationen.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.640 Beiträge
 
#15

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 13:01
Ich habe selbst eine DLL in Delphi geschrieben und einen Wrapper dazu.
Würde ich gerne machen wenn es denn meine DLL wäre.
Ja was denn nun? Ist es Deine Dll, oder nicht?
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#16

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 13:04
Ich habe selbst eine DLL in Delphi geschrieben und einen Wrapper dazu.
Würde ich gerne machen wenn es denn meine DLL wäre.
Ja was denn nun? Ist es Deine Dll, oder nicht?
Damit habe ich gesagt das ich selbst schon für meine eigene DLL einen Wrapper geschrieben habe und dort alles funktioniert.
Nein es ist nicht meine DLL.

Habe oben mal das Beispiel angehängt.
Ohne Quelltext.
Wenn nötig poste ich ihn gern.

gruss
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#17

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 13:10
Zitat:
Du sagst uns nicht, welcher Teil genau in Delphi ist und welcher genau in C#. Aktuell sieht es (zumindest für mich) NICHT danach aus, das Du eine DLL ansprechen willst. Es sieht für mich danach aus, als ob Du ein Stück Delphi-Code 1:1 nach C# portieren = duplizieren willst. Inklusive UI. Das hat mit Bibliotheken/DLL (einmal geschriebener Code, der eben nicht für andere Plattformen kopiert werden muss) ehrlich gesagt genau gar nichts zu tun.
Ich übersetze gar nichts
Das ist gar nicht nett von dir das du mir das unterstellst.. aber egal.
Ich habe die DLL (Wrapper für .NET) und die Anwendung in C# selbst geschrieben. (Nur nochmal zur Klarstellung)
Den Quelltext kannst du im Archiv einsehen. (Aber nicht den der DLL (TagsLib.dll) nicht meine Arbeit)

Alles neu geschrieben außerdem würde eine Übersetzung keinen Sinn machen oder?
Der Delphi Auszug ist aus der API für Delphi Anwendungen die diese DLL verwenden können.
Alle anderen Delphi Quelltextauszüge sind von dem Delphi-Sample das für diese DLL (TagsLib.dll) geschrieben wurde.

Der Source.
http://home.arcor.de/weiss.em/Net_17_04_15.rar

gruss

Geändert von EWeiss (17. Apr 2015 um 13:54 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.640 Beiträge
 
#18

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 14:03
Ahhhhh. Jetzt wird ein Schuh draus

Okay, was ich jetzt sehe:

Du hast also diese TagsLib, die das Handling der Media-Metadaten übernimmt. I see.
Und Du hast ein GUI in C# (und VB.NET) gebaut, das als Beispiel herhalten soll, wie man diese Tagslib verwendet.

Musst Du unbedingt diese dll nutzen, oder kannst Du z.B. auch die Taglib-sharp verwenden, die das ganze auch rein in .NET abhandelt? https://github.com/mono/taglib-sharp/

Wenn Du unbedingt diese nutzen musst:
Das Ding nimmt einen IntPtr auf die Bilddaten. Das entspricht in der Tat am ehesten einem Byte[].
Siehe auch hier:

http://stackoverflow.com/questions/1...using-p-invoke

Also irgendwo ein Byte[] definieren, sicherstellen, das der Garbage collector den nicht wegräumt (wie bei SO beschrieben), und dann auf das Struct .Data den Pointer auf den Beginn des Byte[] legen. Das sollte dann eigentlich die Daten da rüberschaufeln.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#19

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 14:16
Zitat:
Musst Du unbedingt diese dll nutzen, oder kannst Du z.B. auch die Taglib-sharp verwenden, die das ganze auch rein in .NET abhandelt? https://github.com/mono/taglib-sharp/
Es ist ein Gefälligkeit Dienst.
Ich muss die DLL nicht benutzen aber ich möchte dem Entwickler helfen für sein Projekt
eine Möglichkeit zu schaffen das auch andere Developer Sprachen für diese DLL Unterstützt werden.

Für VB6 habe ich das Modul und die Unterstützung schon geschrieben.

Es ist eine reine Gefälligkeit ohne eigenen Nutzen.
Ich helfe halt gern wenn es denn möglich ist.

Zitat:
Das Ding nimmt einen IntPtr auf die Bilddaten. Das entspricht in der Tat am ehesten einem Byte[].
Siehe auch hier:
Das Problem ist die Struct. Irgendwie kommen total falsche Daten an wie im vorherigen Beitrag auf dem Bild zu sehen.
Selbst wenn ich CoverArtData.Data mit IntPtr.Zero übergeben würde dürfte der Aufruf nicht dazu führen.

Zitat:
Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
Allenfalls würde dann ein false zurückgeliefert ohne AV.

Zitat:
Und Du hast ein GUI in C# (und VB.NET) gebaut, das als Beispiel herhalten soll, wie man diese Tagslib verwendet.
Jo Und die unmanaged DLL (TagsLibraryDefs.NET) die als reference eingebunden werden kann. (VB_NET und C#)

Hab im Moment keine Idee wie ich das regeln soll.
Hoffe das mir jemand da helfen kann der mehr Erfahrung hat.
Vielleicht findest du eine Lösung (bzw. kannst das beheben) für das eine Problem wenn du zeit hast natürlich

gruss

Geändert von EWeiss (17. Apr 2015 um 14:28 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#20

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 16:49
Wenn ich das richtig verstanden habe sollte das korrekt sein.
Aber es kracht immer noch.

Code:
byte[] Data = new byte[BitmapStream.Length];
BitmapStream.Read(Data, 0, (int)BitmapStream.Length);

GCHandle DataHandle = GCHandle.Alloc(Data, GCHandleType.Pinned);
IntPtr address = DataHandle.AddrOfPinnedObject();

CoverArtData.Name = Description;
CoverArtData.CoverType = 3;
CoverArtData.MIMEType = MIMEType;
CoverArtData.Description = Description;
CoverArtData.Width = Width;
CoverArtData.Height = Height;
CoverArtData.ColorDepth = ColorDepth;
CoverArtData.NoOfColors = NoOfColors;
CoverArtData.PictureFormat = CoverArtPictureFormat;
CoverArtData.Data = address;
CoverArtData.DataSize = BitmapStream.Length;



if (TagsLib.TagsLibrary_AddCoverArt(Tags, TTagType.ttAutomatic, CoverArtData) != 0)
{
  MessageBox.Show("Error while adding cover art: ", OpenFileDialog1.FileName, MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error);
}
DataHandle.Free();
Muss ich die struct selbst jetzt auch noch pinnen ?

Code:
GCHandle structHandle = GCHandle.Alloc(CoverArtData, GCHandleType.Pinned);
structHandle.Free()
gruss

Geändert von EWeiss (17. Apr 2015 um 17:12 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:47 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz