Hallo,
ich habe eine in C++ geschriebene Dll, die ich im C# Compact Framework nutzen will.
Grundsätzlich ist das auch kein Problem, da dies über DLLImport geht.
Allerdings ist der Aufbau einer Funkion der DLL wie folgt:
int Anmelden(char *ergebnis, char *bmp);
Wie kann ich nun einen Pointer auf die Variable übergeben?
Gruß
maume
Leider sind C-Signaturen nicht aussagekräftig genug um deine Frage ohne weitere Informationen (in/out) zu beantworten.
Wenn aber dein Parameter ein vorallokiertes Char-Array ist, welches von der Funktion gefüllt werden soll (zumindest ergebnis scheint so ein out-Kandidat zu sein) dann musst du StringBuilder verwenden. Also ein StringBuilder-Objekt mit der passenden Länge erzeugen und reinstecken.
Ich habe nun folgenden Code:
[DllImport("terminal.dll")]
unsafe private static extern int Anmelden(ref StringBuilder ergebnis, ref StringBuilder bmp);
StringBuilder ergebnis = new StringBuilder(2);
StringBuilder bmp = new StringBuilder(257);
i = Anmelden(ref ergebnis, ref bmp);
Wenn ich das nun ausführe geht auch alles gut, bis zum Aufruf von Anmelden.
Da bekomme ich als Exception
Can't find PInvoke DLL 'terminal.dll'.
Die DLL liegt im gleichen Verzeichnis, wie die ausgeführte EXE.
Könnt ihr mir damit auch helfen?
Die Fehlermeldung tritt auch auf, wenn nicht genug Speicher zur Verfügung steht um die DLL zu laden.
Kann es evtl. auch damit zu tun haben, dass die DLL ursprünglich für Win32 geschrieben ist?
Dann müsste ich den Entwickler noch mal ansprechen, ob ich die DLL auch für WinCe haben kann.
Default-Marshalling auf CE ist Unicode. char* ist aber ANSI. Also CharSet=CharSet.Ansi im DLLImportAttribute.
Ich kann im DLLImport aber nur Unicode oder Auto einstellen.
Wenn ich das ganze nun so mache
[DllImport("terminal.dll", CharSet = CharSet.Auto,SetLastError= true, EntryPoint = "Anmelden")]
unsafe private static extern int Anmelden(ref StringBuilder ergebnis, ref StringBuilder bmp);
kommt leider immer noch die PInvoke Exception.
Stimmt. Dann empfehle ich: Benutze die OpenNETCF-Lib. Da gibts die Klasse Marshal2 und dort eine Funktion PtrToStringAnsi().
Dann musst du anstelle des StringBuilders den Parameter IntPtr nutzen. Mittels Marshal.AllocGobalH Speicher reservieren und dann via IntPtr übergeben. Nach unmanaged Aufruf mit PtrToStringAnsi() den Inhalt des Speichers in einen String kopieren. Dann den Speicher mit MArshal.FreeGlobalH freigeben.
Leider wäre es natürlich die unmanaged Funktion in Unicode zu ändern (wchar*).