Frage

Ich arbeite an einem PInvoke Wrapper für eine Bibliothek, die nicht Unicode-Strings nicht unterstützt, aber Multi-Byte-ANSI-Zeichenfolge nicht unterstützt. Während der Untersuchung FxCop auf der Bibliothek berichtet, bemerkte ich, dass die Zeichenfolge Serialisieren hatte einige Effekte interessante Seite verwendet wird. Die PInvoke Methode wurde mit "best fit" Mapping eine Single-Byte-ANSI-Zeichenfolge zu erstellen. Zur Veranschaulichung ist das, was eine Methode sah aus wie:

[DllImport("thedll.dll", CharSet=CharSet.Ansi)]
public static extern int CreateNewResource(string resourceName);

Das Ergebnis dieser Funktion mit einem String aufrufen, die Nicht-ASCII-Zeichen enthält, ist, dass Windows ein „close“ Charakter findet, in der Regel das sieht aus wie es endet als „???“. Wenn wir behaupten, dass 'a' ist ein Nicht-ASCII-Zeichen, dann "cat" als Parameter übergeben würde eine Ressource erstellen namens "c? T".

Wenn ich die Richtlinien in der FxCop Regel folgen, ich am Ende mit etwas wie folgt aus:

[DllImport("thedll.dll", CharSet=CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern int CreateNewResource([MarshalAs(UnmanagedType.LPStr)] string resourceName);

Dies führt zu einer Änderung des Verhaltens; jetzt, wenn ein Zeichen nicht zugeordnet werden wird eine Ausnahme ausgelöst. Dies betrifft mich, weil dies eine unterbrechende Änderung ist, so würde Ich mag die Saiten als Multi-Byte-ANSI versuchen und Marschall, aber ich kann nicht einen Weg dies zu tun, sehen. UnmanagedType.LPStr spezifiziert ein Single-Byte-ANSI-Zeichenfolge zu sein, LPTStr will be Unicode or ANSI depending on the system, and LPWStr is not what the library expects.

How would I tell PInvoke to marshal the string as a multibyte string? I see there's a WideCharToMultiByte() API function, could I change the signature to expect an IntPtr in einen String I in nicht verwalteten Speicher erstellen? Es scheint, wie dies immer noch viele Probleme hat, die die aktuelle Implementierung hat (es noch fallen lassen oder Ersatzzeichen können müssen), so bin ich nicht sicher, ob dies eine Verbesserung. Gibt es eine andere Methode der Serialisieren, die ich fehle?

War es hilfreich?

Lösung

ANSI ist Multi-Byte-und ANSI-Zeichenfolge codiert sind nach der Codepage zur Zeit auf dem System aktiviert. WideCharToMultiByte funktioniert auf die gleiche Art und Weise wie P / Invoke.

Vielleicht sind Sie nach, was Umstellung auf UTF-8. Obwohl WideCharToMultiByte dies unterstützt, glaube ich nicht, P / Invoke der Fall ist, da es nicht möglich ist UTF-8 als systemweite ANSI-Codepage zu übernehmen. An diesem Punkt würden Sie die Zeichenfolge als IntPtr bei Passieren statt suchen, obwohl, wenn Sie das tun, auch Sie können die verwaltete Encoding-Klasse verwenden, um die Konvertierung zu tun, anstatt WideCharToMultiByte.

Andere Tipps

Hier ist der beste Weg, die ich gefunden habe, dies zu erreichen. Anstelle von [] als String, Marschall als Byte-Rangier. Legen Sie die Verantwortung auf dem Aufrufer der pinvoke Funktion API auf einen Byte-Array in der am besten geeigneten Art und Weise umzusetzen. Wahrscheinlich durch eine der Text.Encoding Klassen.

Wenn Sie am Ende mit WideCharToMultiByte manuell nennen, würde ich loswerden der p erhalten / aufrufen und manuell Marschall dies mit WideCharToMultiByte in einer C ++ / CLI Wrapper-Funktion. Managed C ++ ist viel besser an diesen Interop-Szenarien als C # ist.

Obwohl, wenn dies die einzige p / aufrufen Sie haben, ist es wahrscheinlich nicht wert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top