Laden...

DLL-Funktion mit Zeigern als Parameter

Letzter Beitrag vor 19 Jahren 11 Posts 2.474 Views
DLL-Funktion mit Zeigern als Parameter

Hallo Leute,

ich versuche gerade eine C++-DLL mit PInvoke in mein C#-Programm reinzubasteln, aber außer einer 'System.ExecutionEngineException' bekomme ich nichts wieder. Ich denke ich habe die beiden folgenden Probleme:

  1. es werden Zeiger verwendet
  2. Die Parameterübergabe ist nicht Standardwindows, sondern c-spezifisch.

Hier mal die C++ Funktion


typedef unsigned char *FEAL_sk;

extern "C" __declspec(dllexport) void FEAL_key_schedule(FEAL_sk key, FEAL_sk keytab, FEAL_sk fkp);

und das ich mir daraus in C# gebastelt habe

		
[DllImport ("conv32.dll")]
extern static void _FEAL_key_schedule(ref byte[] key, ref byte[] keytab, ref byte[] fkp );


Kann mir irgendjemand nen Tip geben.


Gruß
Uwe

Erstmal musst die Aufrufkonvention im DLLImport angeben. Default ist stdcall und nicht cdecl:

[DllImport ("conv32.dll", CallingConvention=CallingConvention.Cdecl)]

Die Byte-Arrays kannst du durch einfache Strings ersetzen, es sei denn, die Methode modifiziert die Strings.

Hallo svenson,

das mit der CallingConvention hatte ich mittlerweile auch schon gefunden. Das mit den Strings werde ich mal ausprobieren.

Wobei meine DLL die Strings modifiziert!!


Gruß
Uwe

Dann nimm den StringBuilder. Ach so, die Standard-Zeichenumwandlung ist Auto und somit Unicode. Wenn du normales ANSI auf der unmanaged Seite erwartest, dann musst du im DLLImport noch

CharSet = Ansi

mit angeben.

Irgendwas ist immer noch faul, da ändert sich nichts an meinen "strings", die eigentlich nur binärdaten enthalten. Aber zumindest kracht es nicht mehr.


Gruß
Uwe

Wie gesagt, StringBuilder verwenden. Wenn es sich aber bei deinem "char*" in Wirklichlichkeit um ein verkapptes Byte-Array mit Binärschleim handelt, dann wird das nicht funktionieren.

Versuche doch mal die "harte" Variante. Definiere bei den char*-Parametern ein "IntPtr" als Typ und kopiere dein byte[] mittels der Methoden in der Marshal-Klasse in unmanaged Speicher um und übergebe diesen. Hier muss du aber noch für die Freigabe des Speichers sorgen.

Wenn es aber Binär-Schleim ist, wie erkennst du dann das Feld-Ende (ich sehe keinen Längen-Parameter)? Kannst du sicherstellen, dass deine Daten keine "0" enthalten?

Wenn es aber Binär-Schleim ist, wie erkennst du dann das Feld-Ende (ich sehe keinen Längen-Parameter)? Kannst du sicherstellen, dass deine Daten keine "0" enthalten?

Die Arrays die ich Übergebe haben fixe Längen die auch der DLL bekannt sind. Nullen kann ich natürlich bei Binärdaten nicht vermeiden.

Versuche doch mal die "harte" Variante. Definiere bei den char*-Parametern ein "IntPtr" als Typ und kopiere dein byte[] mittels der Methoden in der Marshal-Klasse in unmanaged Speicher um und übergebe diesen. Hier muss du aber noch für die Freigabe des Speichers sorgen.

Na dann also zurück zum guten alten Zeiger mit Speicher den man auch wieder freigibt. Die lassen einen somit auch im .NET-Zeitalter nicht los. Ich probiers morgen früh mal aus.


Gruß
Uwe

Urgs, da hast du mich aber gut auf eine falsche Fährte geführt. Deine C++-Definition ist ja bereits falsch. Ein char* ist nunmal keine Byte-Array fester Länge..... 🙂

Wenn du eh ein Byte-Array fester Länge hast, dann verwende Marshall.Copy() und IntPtr. Du muss nach der Funktion die Daten allerdings wieder zurückkopieren.

Was die Länge angeht: Die sollte nicht nur deine DLL kennen, sondern auch dein .NET-Code. Du musst nämlich Bytes kopieren, dazu musst du wissen wie viel.

Üblicherweise weiss nur der Aufrufer um die Länge von Arrays, bzw. muss sie als Parameter reinreichen. Sehr ungewöhnlich deine DLL....

Ein char* ist nunmal keine Byte-Array fester Länge.....

Das stimmt! Ein char* ist schlicht und ergreifend ein Zeiger auf einen char. Ob da jetzt was mit fester Länge oder ein nullterminierter String hinter steht ist damit noch in keinster Weise festgelegt.

Üblicherweise weiss nur der Aufrufer um die Länge von Arrays, bzw. muss sie als Parameter reinreichen. Sehr ungewöhnlich deine DLL....

Es gibt auch WINAPI-DLL's die für einen den Speicher allokieren und man einfach nur den Zeiger übergibt. Aber ich gebe durchaus zu das die DLL recht merkwürdig ist und da der Source-Code vorhanden ist werde ich sie auch mal bei Gelegenheit portieren.


Gruß
Uwe

Kaum macht mans richtig, schon funktionierts! Immer wieder erstaunlich.

Noch mal meinen Dank für den Tip mit dem Marshal.


Gruß
Uwe

Wenn der AUFGERUFENE den Speicher allokiert, dann ist der Parametertyp aber char**, da die Adresse ja noch unbekannt ist.

Naja, Hauptsache es funzt....