Entwickler-Ecke
Windows API - Daten aus unmanagged code in managed code übernehmen
ASMFreak - Mo 30.01.12 14:00
Titel: Daten aus unmanagged code in managed code übernehmen
Hallo, liebe Community,
manchmal wünsche ich mir die guten, alten Pointer zurück!
Ich habe ein Problem, mit dem ich noch keine Erfahjrung habe, da ich bislang entweder im unmanaged code herumgewerkelt habe, ODER im managed. Jetzt habe ich aber ein Problem, das beides betrifft.
Ich benötige Informationen aus unmanaged code in Form einer Liste von GUIDs. Um die zu ermitteln, gibt es eine Schnittstellenfunktion, die wie folgt deklariert ist:
C#-Quelltext
1: 2: 3: 4:
| HRESULT GetIds( [out] GUID **ppId, [in, out] UINT *pCount ); |
Die versuche ich, mit Delphi anzusprechen. Daher habe ich einen Delegaten deklariert nach
Delphi-Quelltext
1:
| funktion GetIDs(out pKD: KommtGleich; out Count: Integer): HResult |
Das Natürliche wäre nun, eine Variable
Delphi-Quelltext
1: 2: 3: 4:
| type TGUIDArray = Array of TGUID; var GUIDArray: TGUIDArray |
zu deklarieren und der Funktion zu übergeben. Tut man das, erhält man die Exception "Es wurde ein SafeArray vom Rang 14852 an eine Methode übergeben, die ein Array vom Rang 1 erwartet hat." OK! Das ist dar Problem der Datenübertragung zwischen unmanaged und managed code, wie ich vermute. Also: marshallen. Aber: wie? Meine diversen Versuche haben nichts gebracht.
Also zweiter Versuch:
Delphi-Quelltext
1:
| function GetIDs(out pKD: IntPtr; out Count: Integer): HResult; |
Und der Vesuch, analog zur damaligen Zuweisung eines PGUIDArray an eine Variable das Problem zu lösen. Aber auch hier führten meine Versuche des Marshallens nicht zum Erfolg. Entweder, der zurückgegebene Pointer erzeugte eine Exception nach dem Motto: "Es wurde versucht, in geschütztem Code zu lesen oder zu schreiben" oder so ähnlich, oder der Versuch, dass array auszulesen, wurde mit der Meldung bestraft, dass der Index den erlaubten Bereich überschreitet - auch beim Index 0 und obwohl mir Count sehr glaubhaft mitteilt, dass es jede Menge Einträge in der Liste gibt.
Kann mir jemand helfen?
Gruß,
ASMFreak
mandras - Mo 30.01.12 14:52
auch wenn meine c-zeiten lange zurückliegen, wie wäre es mit:
Delphi-Quelltext
1: 2: 3: 4:
| type TGUIDArray = Array [0..10000] of TGUID;
funktion GetIDs(var pKD: TGUIDArray; var Count: Integer): HResult |
der Unterschied array of und array [0 .. 10000] of:
bei ersterem "bastelt" der Compiler noch etliches herum um mit diesem dynamischen Array arbeiten zu können damit auch Funktionen wie setlength etc. funktionieren.
Durch die var-Definition der Variablen übergibt der Compiler beim Funktionsaufruf nur die Adresse der Variablen an die aufgerufene Funktion, was diese damit macht und evtl. dort Werte änert ist ihm dann egal.
Die Grenze 10000 habe ich willkürlich gewählt.
ASMFreak - Mo 30.01.12 15:09
Habe ich vergessen zu sagen: Natürlich habe ich es auch damit versucht: Mit dem gleichen Ergebnis. Es schient kein Problem des "Herumbastelns" beim dynamischen Array zu sein, sondern ein Problem, an strukturierte Daten aus einem unmanaged code-Bereich zu kommen.
mandras - Mo 30.01.12 15:19
Hast Du die Funktion als stdcall definiert? liegt sie evtl. sogar in einer DLL?
ASMFreak - Mo 30.01.12 15:58
Nein, sie ist Teil einer Schnittstellendefinition. Wenn ich da mit "stdcall" ran gehe, meckert der Compiler, dass das bei externen Deklarationen nicht erlaubt sei!
Das Ganze sieht wie folgt aus (ich kopiere jetzt nicht die ganze Unit, daher nur das Prinzip):
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| unit Test;
interface
type [ComImport, GuidAttribute ... ISchnittstelle = interface : : [PreserveSig] function GetIDs(out ppkFID: TGUIDArray; var Count: Integer): HResult; : : end; |
später wird dann eine Klasse definiert, in der dann steht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| type EineKlasse = class(TObject) : public : procedure GetTheIDs(Ifc: ISchnittstelle); : end; |
Und im Implementationsteil folgt dann
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure EineKlasse.GetTheIDs(Ifc: ISchnittstelle); var IDs: TGUIDArray; Count: Integer; begin OleCheck(Ifc.GetIDs(IDs, Count)); end; |
Das funktioniert mit allen anderen Methoden der Schnittstelle hervorragend, nur diese zickt rum. Zugegeben: Alle anderen Methdoen haben auch "einfache" Daten wie Strings oder Uints. Diese hier hat strukturierte Daten (Array). Und, wie gesagt, es ist egal, ob TGUIDArray = Array of TGUID oder TGUIDList = Array[0..irgendwas] of TGUID.
mandras - Mo 30.01.12 17:04
Da muß ich leider passen, evtl. würde das Debug/CPU-Fenster weiterhelfen?
ASMFreak - Mo 30.01.12 17:11
Nicht wirklch! Danke trotzdem!
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!