Export-dll-Methode von C++ zu C#. Warum Brauch ich: "extern "C" "
In meine dll ist eine Methode, die ich exportieren möchten.
//Funktioniert:
extern "C" __declspec(dllexport)
//Wird nicht funktionieren
__declspec(dllexport)
C++ Export:
extern "C" __declspec(dllexport) int Test();
C# importieren:
[DllImport("CircleGPU2_32.DLL", EntryPoint = "Test",
CallingConvention = CallingConvention.StdCall)]
public static extern int Test();
Warum brauche ich die extern "C" ?
- Ich habe eine detaillierte Erklärung, warum es erforderlich ist, wenn Sie interessiert sind.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der Hauptgrund ist, um zu verhindern, dass der C++ - name mangler von mangeln der name der Funktion.
Versuchen zu exportieren, ohne die
extern "C"
und untersuchen Sie die resultierende DLL in Dependency Walker und Sie werden sehen, einen ganz anderen Namen für die exportierte Funktion.Dies ist durch name mangling durchgeführt von C++.
extern "C" vs keine extern "C"
Als ein Beispiel hier ist, was CFF-Explorer zeigt für eine dll export-Tabelle. Die erste wurde mit borland c++ compiler. Die zweite wurde mit msvc.
Den ersten 2 Funktionen
createDevice
undcreateDeviceEx
enthalten dieextern "C"
Signatur in der Prototypen, während der andere nicht. Auf den Unterschied in der Codierung, wenn C++ - mangling verwendet wird. Der Unterschied geht eigentlich tiefer als das.ABI & Standardisierung
Wie bereits in den anderen Antworten, die C++ - standard keine nicht geben Sie eine Einebstract Binary ichnterface. Das bedeutet, dass die Anbieter, die Gestaltung Ihrer tools kann so ziemlich alles tun, was zum Teufel Sie wollen, wenn es darum geht, wie Funktionsaufrufe behandelt werden und wie überlastung, arbeitet unter der Haube-so lange zeigt das erwartete Verhalten diktiert von der Norm.
Mit all diesen verschiedenen Kodierungsverfahren es gibt keine Möglichkeit, eine andere Sprache können, haben jede Hoffnung auf die Arbeit mit kompilierten Modulen, die mit C++. Heck-Module mit kompiliert man C++ - compiler ist es unwahrscheinlich, dass die arbeiten mit einem anderen! Compiler-Hersteller sind frei, zu ändern, deren Codierung zwischen den Versionen in Ihrem Ermessen.
Darüber hinaus keine gemeinsame ABI bedeutet es gibt keine gemeinsame erwarteter Weise zu nennen, die in diese Funktionen/Methoden. Zum Beispiel, einen compiler könnte, gehen seine Argumente auf dem stack, während ein anderer compiler könnte es passieren, auf das register. Man könnte Argumente von Links nach rechts, während ein anderer könnte rückgängig gemacht werden. Wenn nur einer dieser Aspekte nicht exakt übereinstimmen zwischen dem Anrufer und der angerufene dann die app Abstürzen... das heißt, wenn Sie Glück haben. Statt sich mit diesem Anbieter einfach Nein sagen und erzwingen ein build-Fehler mit den verschiedenen Codierungen.
OTOH, während C nicht über ein standardisiertes ABI entweder, C ist eine viel einfachere Sprache zu befassen sich mit Vergleich. Die meisten C-compiler-Hersteller handle-Funktion, Dekoration und call-Mechanismus in einer ähnlichen Weise. Als Ergebnis gibt es eine Art "de-facto" - standard, auch wenn ein ABI ist nicht explizit in der Norm festgelegt sind. Mit dieser gemeinsamkeit, es macht es viel einfacher für andere Sprachen, um eine Schnittstelle mit Modulen zusammengestellt, mit C.
Beispielsweise eine
__stdcall
Dekoration in einer Funktion, die Signatur verstanden, die Folgen einer bestimmten Aufruf-Konvention. Argumente sind gedrückt rechts-nach-Links-und der angerufene ist verantwortlich für die Reinigung der Stapel anschließend.__cdecl
ist ähnlich, aber es ist verständlich, dass die Anrufer ist verantwortlich für die Reinigung der stack.Die Bottomline
Wenn das Modul in Frage, muss kompatibel sein mit Sprachen außerhalb von C++, dekorieren Sie entsprechend und setzen Sie es wie ein C-API ist Ihre beste Wette. Beachten Sie, dass Sie aufgeben, einige Flexibilität, dies zu tun. Insbesondere werden Sie nicht in der Lage sein, um eine überlastung dieser Funktionen, da der compiler kann keine mehr erstellen von eindeutigen Symbolen für jede überladung mit name mangling.
Wenn die Interoperabilität nicht von Bedeutung Modul in Frage-es ist nur gehen, um verwendet werden mit dem gleichen tool es erstellt wurde, dann lassen Sie die
extern "C"
Dekoration von Ihrem Prototypen.Den compiler normalerweise schmückt Ihre exportierten Namen, um Informationen über die Klasse und die Unterschrift.
extern "C"
sagt dem compiler, das nicht zu tun.extern "C"
Stoppt eine form der Dekoration, mangeln, aber andere Dekoration können noch existieren. Zum Beispielstdcall
Methoden sind in der Regel dekoriert mit einem_
Präfix und ein@N
suffix, wobei N die stack-Größe. msdn.microsoft.com/en-us/library/zxk0tw93(v=VS.100).aspxIch habe versucht, dies mit einer Funktion mit 1 parameter und Sie müssen
für den import in C# zu arbeiten. Stdcall-Anweisung funktioniert nur (in der vorgestellten situation, nicht im Allgemeinen ) für Funktionen ohne Parameter und die Rückgabe ungültig.
Getestet in vs2012 express edition.