2016-08-02 31 views
10

Wenn ich erklären, eine Funktion wie folgt aus:DLL mit __stdcall ohne Namen Dekoration: Warum funktioniert es überhaupt?

#ifdef TEST_EXPORTS 
#define TEST_API __declspec(dllexport) 
#else 
#define TEST_API __declspec(dllimport) 
#endif 

TESTAPI int __stdcall myadd(int a, int b); 

Das Symbol in der DLL ist [email protected], die mir durchaus Sinn macht (nach wenigen Stunden des Lesens andere Fragen hier, das ist).

Aber die Windows-Bibliotheken scheinen etwas anderes zu tun. Sie verwenden auch __stdcall (getarnt als WINAPI), aber die Symbole in den DLLs haben keinen Namen Dekoration. Wenn die obige Methode in den Windows-Bibliotheken wäre, wäre das Symbol myadd.

Meine Vermutung ist, dass sie eine def-Datei verwenden, um die Symbole zu aliasieren. Aber warum weiß mein Linker das, wenn ich auf eine dieser DLLs verlinke?

Die Windows-Header-Dateien deklarieren diese Funktionen mit WINAPI, also wenn ich sie aufrufen, sollte der Linker nach dem verzierten Namen suchen, da es eine __stdcall-Funktion ist. Doch irgendwie weiß der Linker, dass er die Namensdekoration fallen lässt.

Ich habe versucht, dies zu replizieren, indem Sie eine kleine DLL schreiben und die Namensdekoration mit einer def-Datei entfernen. Wie erwartet, bekomme ich Linkfehler, da der Linker immer noch nach dem dekorierten Namen sucht. Ich habe das in reinem C getan, um sicherzustellen, dass C++ Name Mangling es nicht beeinflusst.

edit: zu klären, MSVC 14,0/VS2015, 32-Bit-

+0

Beachten Sie, dass x64 keine Namensdekoration verwendet. –

+0

@ JonathanPotter: * "Beachten Sie, dass x64 keine Namen Dekoration verwendet." * - Das ist nur für 'extern" C ". C++ - Symbole müssen Exportnamen für die Überladungsauflösung aufweisen. – IInspectable

Antwort

6

Es gibt einige kaum dokumentiert Magie hier bei der Arbeit. Lets look einige WIN32API Funktion, wie RegQueryValueExW. Es ist in der winreg.h Datei wie folgt definiert:

WINADVAPI LSTATUS APIENTRY RegQueryValueExW(...); 

Wo WIADVAPI ist ein __declspec(dllimport) und APIENTRY ein Moniker für die __stdcall Namenskonvention ist. Beachten Sie auch, dass alle Funktionen im Header als extern "C" deklariert sind. Also auf jeden Fall sollte diese Funktion Name Dekoration verwenden, und seine DLL-Export sollte [email protected] sein. Doch wenn wir advapi32.dll Exporte suchen dumpbin /exports Befehl, sehen wir eine undecorated Name:

advapi exports

nun eng advapi32.lib Datei mit dumpbin /headers advapi32.lib Befehl können prüfen:

enter image description here

Notiere die undecorate Spezifizierer, Damit kann der dekorierte Name mit dem undekorierten Export verknüpft werden. Sie können das gleiche Ergebnis für Ihre DLL mit einer def Datei mit EXPORTS Abschnitt mit undekorierten Namen erreichen. Weitere Informationen finden Sie unter this Artikel und this answer.

Auch alles oben beschriebene ist nur für die x86-Anwendungen gültig. C-Funktionen in der x64-Bit-Umgebung without name decoration verbunden:

Die Form der Dekoration für eine C-Funktion auf dem rufenden convention hängt in ihrer Erklärung verwendet werden, wie in der folgenden Tabelle dargestellt. Dies ist auch das Dekoformat, das verwendet wird, wenn der C++ - Code mit der externen C-Verknüpfung deklariert ist. Die Standard-Aufrufkonvention lautet __cdecl. Beachten Sie, dass Funktionen in einer 64-Bit-Umgebung nicht eingerichtet sind.

+0

Das ist es. Ich habe versucht, clever zu sein und dekorierte Namen in die Def-Datei zu schreiben. Die lib ist in der Tat das fehlende Glied. Es definiert das dekorierte Symbol und leitet den Aufruf an das undekorierte DLL-Symbol weiter. – Stefan