Wickeln Sie die native DLL für C#
Schrieb ich eine C++ DLL und jetzt muss ich anrufen eine systemeigene Funktion, die von einer verwalteten app.
Die exportierte native Funktion erscheint wie diese:
extern "C" __declspec(dllexport)
bool NativeMethod(char *param1, char *param2, char *result);
So, in der C# - ich rufe die Funktion übergeben 2 input params, 1 Ausgang param und natürlich werde ich Lesen die Rückgabe boolescher Wert.
Habe ich versucht zu wickeln, all dies in vielerlei Hinsicht, aber immer bekomme ich eine PInvokeStackImbalance
Ausnahme.
Ich weiß nur einen Weg zu nennen, native Funktion wird durch die Anwendung CallingConvention = CallingConvention.Cdecl
) auf .NET-Funktion Erklärung. Aber auf diese Weise bin ich nicht in der Lage zum Lesen der Ausgabe-param (einen leeren string immer) und auch der Rückgabewert ist immer true.
- was den import haben u versucht?
- Ich habe versucht, so etwas wie: [DllImport("MyDll", EntryPoint = "NativeMethod")] public static extern Boolean NativeMethod(string param1, string param2, string param3); Auch mit out param3 oder StringBuilder oder MarshalAs(UnmanagedType.LPStr)]
- Sie erkennen, dass diese output-parameter funktioniert nicht, richtig? C# - strings unveränderlich.
- [DllImport("MyDll.dll", EntryPoint = "NativeMethod", CallingConvention = CallingConvention.Cdecl)] static extern bool NativeMethod( [MarshalAs(UnmanagedType.LPStr)]string param1, [MarshalAs(UnmanagedType.LPStr)]string param2, [MarshalAs(UnmanagedType.LPStr)]string param3); - chk meine Antwort!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Zuerst möchte ich anpassen, der Prototyp des nativen Funktion.
Da diese Funktion hat eine C-Schnittstelle, sollten Sie eine C-Typ für boolsche Variablen, nicht um eine C++ - Typ wie
bool
. Sie verwenden möchten, können Win32 istBOOL
geben.Außerdem, wie es derzeit ist, Ihre Funktion ist anfällig für Pufferüberläufe: es ist besser, fügen Sie einen anderen parameter geben Sie die maximale Größe des Ziel -
result
string-Puffer.Beachten Sie auch, dass eine weit verbreitete Aufrufkonvention für DLLs exportieren reines C-interface-Funktionen (wie viele Win32-API-Funktionen) ist
__stdcall
(nicht__cdecl
). Ich würde verwenden, wie gut.Zuletzt, da die ersten beiden Parameter sind Eingang Zeichenfolgen, die Sie verwenden möchten, können
const
deutlich zu machen und durchzusetzen, const-correctness.So, ich würde der Prototyp die exportierte native Funktion wie diese:
Dann, auf der C# Seite, können Sie die folgenden P/Invoke:
Beachten Sie, dass für die Ausgabe einer Zeichenfolge, einer
StringBuilder
verwendet wird.Beachten Sie auch, dass
CharSet = CharSet.Ansi
wird verwendet, um den Marschall C#'s Unicode UTF-16-Zeichenfolgen in ANSI (achten Sie auf die Tatsache, dass die Konvertierung verlustbehaftete - wenn Sie möchten, eine verlustfreie Konvertierung, verwenden Sie einfachwchar_t*
Saiten auf C++ - Seite als auch).Ich habe einen test mit einem einfachen C++ systemeigene DLL:
Genannt, der erfolgreich von den folgenden C# - Konsolenanwendung-code:
Sparen Sie sich eine Menge von P/Invoke-Kopfschmerzen, wenn Sie nur die Verwendung von COM-Interop statt. Setzen Sie die Methode in einer COM-Schnittstelle und ändern Sie die Signatur zu Folgen COM-Konventionen:
Änderte ich char* zu BSTR und bool zu VARIANT_BOOL, denn diese sind die Typen von COM verwendet für strings, bools und, beziehungsweise. Auch alle COM-Methoden zurückkehren müssen eine HRESULT. Wenn Sie möchten, dass eine "tatsächliche" Wert zurückgeben, müssen Sie es hinzufügen, wie der Letzte aus parameter und auch markieren Sie es mit der retval Attribut.
Dann fügen Sie einen Verweis auf die COM-Komponente aus C# - Projekt, und Sie werden eine intuitive C# - Signatur, ohne zu erraten, wie C++ - Typen mit C# - Typen:
(Das ist, wie es scheint, im Objekt-Browser.)
warum Hinweis mit .Net-code marshalling mit DLLImport wie die folgenden
und dann können Sie die Funktion aufrufen, die als lokale Funktion wie die folgende
Ersetzen
LPStr
mitLPWStr
wenn Sie die Arbeit mit wide-chars.Den output-parameter einer
char *
, da C# strings sind unveränderlich. Rufen Sie die Methode (in einem unsicheren Kontext) so:Es sei denn, die Ausgabe-parameter ist kein string sondern nur ein einzelnes Zeichen, in dem Fall kann man nur dazu:
Und Sie können es einfach verwenden, wie diese:
int
als Rückgabewert stattbool
?