2010-10-19 13 views
7

Ich habe eine nicht verwaltete C++ DLL, die ich von einer Windows Mobile C# -App aufrufen muss.Übergabe einer C# Zeichenfolge an eine nicht verwaltete C DLL in Windows Mobile

Ich habe die C# -Wrapper und es funktioniert gut in Desktop. Ich kann die DLL-Funktionen von einem C# -Desktopprogramm aufrufen und Strings ohne Probleme weitergeben.

Wenn ich jedoch die Bibliothek und den Wrapper für die mobile Plattform kompilieren, erhalte ich einen Fehler in den DllImport Zeilen, die besagt, dass CharSet.ANSI nicht erkannt wird. Die einzigen Optionen, die ich schreiben darf, sind CharSet.Auto und CharSet.Unicode.

Das Problem ist, dass unabhängig von dieser Einstellung die Zeichenfolgen, die in den C++ - Funktionen empfangen werden, Wide-Zeichenfolgen und keine normalen Zeichen * Zeichenfolgen sind, was sie erwarten.

Wir wcstombs() verwenden alle Strings am Anfang jedes C++ Funktion zu übersetzen, aber ich möchte lieber nicht die lib in einem solchen Ausmaß ändern ...

Gibt es eine Möglichkeit das zu beheben Marshalling zwischen C# und C, die mit dem .NET Compact Framework funktioniert?

+0

[Social.msdn] (http://social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/4aed0776-638a-4fde-ad61-e2462b39a961) sagt nein :( – GSerg

Antwort

6

Nein, gibt es nicht.

Microsoft documentation gibt an, dass:

[...] .NET Compact Framework nur Unicode unterstützt, und folglich sind nur die CharSet.Unicode ( und CharSet.Auto die Unicode entspricht) Wert, und unterstützt keine der Klauseln der Declare-Anweisung. Dies bedeutet, dass die ExactSpelling-Eigenschaft auch nicht unterstützt wird.

Als Ergebnis, wenn Ihre DLL-Funktion erwartet eine ANSI-Zeichenfolge, Sie benötigen die Umwandlung in der DLL, oder konvertieren Sie die Zeichenfolge in einem Byte-Array mit der überladenen GetBytes Methode der auszuführen ASCIIEncoding Klasse, vor Aufruf der Funktion, da das .NET Compact Framework immer einen Zeiger auf die Unicode-Zeichenfolge übergeben wird. [...

]

Die Lösung lautet:

Funktionen in der DLL

int MARSHALMOBILEDLL_API testString(const char* value); 
const char* MARSHALMOBILEDLL_API testReturnString(const char* value); 

Wrapper

[DllImport("marshalMobileDll.dll")] 
public static extern int testString(byte[] value); 

[DllImport("marshalMobileDll.dll")] 
public static extern System.IntPtr testReturnString(byte[] value); 

Coderuf

string s1 = "1234567"; 
int v = Wrapper.testString(Encoding.ASCII.GetBytes(s1)); 

string s2 = "abcdef"; 
IntPtr ps3 = Wrapper.testReturnString(Encoding.ASCII.GetBytes(s2)); 
string s3 = IntPtrToString(ps3); 


private string IntPtrToString(IntPtr intPtr) 
{ 
    string retVal = ""; 

    byte b = 0; 
    int i = 0; 
    while ((b = Marshal.ReadByte(intPtr, i++)) != 0) 
    { 
    retVal += Convert.ToChar(b); 
    } 
    return retVal; 
} 
+0

Endlich! Explizite Konvertierung scheint die einzig mögliche Lösung zu sein ... Vielen Dank, es funktioniert jetzt einfach super! – matpop

2

Windows CE ist stark auf Unicode ausgerichtet (die meisten Win32-APIs haben nicht einmal ANSI-Entsprechungen). Daher ist die CF mit ANSI auch nicht wirklich gut und sie braucht ein wenig "Hilfe", um es richtig zu machen.

Sie können die Marshaler sagen, dass Sie die Daten als Single-Byte übergeben wollen, null beendet Werte durch das MarshalAs Attribut (the MSDN docs zeigen deutlich, es wird in der CF-unterstützt), etwas in dieser Richtung:

[DllImport("mydll.dll", SetLastError = true)] 
public static extern void Foo([MarshalAs(UnmanagedType.LPStr)]string myString); 
+0

leider MarshalAs wird nicht unterstützt unter Compact Framework – tato

+0

Nach wem? MarshalAs sicherlich * wird * unterstützt. Ich benutze es ziemlich regelmäßig und ich mache fast nichts als CF Arbeit. – ctacke

+0

MSDN sagt unterstützt seit 3.5 SP1 –