2016-09-28 1 views
0

Ich habe irgendwo gehört, dass alle Windows-.DLLs Muss Definitionen für jedes Symbol enthalten sie verweist, so dass eine DLL-Datei wie dies würde nie kompilieren, da es nicht bar() nicht implementiert.Compile .dll mit einigen undefinierte Referenzen mit MinGW

void bar(); 

__declspec(dllexport) 
void foo() { 
    bar(); 
} 

Ich denke, die Analogie ist, dass .DLLs ist im Wesentlichen Executables mit einem anderen Einstiegspunkt, so müssen sie alle definierten Bezug genommen wird, wie eine ausführbare Datei.

Aber in einer Unix-Umgebung kann ich dies zu einer .so-Datei ohne Probleme kompilieren. Ich kann dann dlopen(path, RTLD_NOW | RTLD_GLOBAL); von der Host-Anwendung verwenden, um die Bibliothek zu laden und die Symbole des Hosts mit denen der Bibliothek zusammenzuführen. Wenn der Host bar() definiert, ruft die Bibliothek diese Funktion einfach auf.

Ich kann nicht einfach alles in die .DLL-Datei neu definieren, weil die Bibliothek in meiner Anwendung Tausende von Symbolen vom Host verwendet. Kann man mit MinGW oder möglicherweise Visual C++ wirklich kein Symbol vom Host verwenden, indem man es in der .DLL undefiniert lässt und beim Laden zusammenfügt? Ich möchte auch nicht Tausende von Callback-Funktionen in der .DLL setzen, weil das mit C++ - Methoden schwierig wird.

+2

Sie gehört zu Unrecht kompilieren. Eine Windows-DLL kann ein Symbol aus der ausführbaren Datei verwenden, die es lädt, obwohl es etwas ungewöhnlich ist. Sie exportieren die Funktion einfach aus der ausführbaren Datei (z. B. mit '__declspec (dllexport)') und importieren sie in die DLL (z. B. mit '__declspec (dllimport)'). –

+0

... obwohl ich jetzt daran denke, weiß ich nicht, ob MinGW das unterstützt. Ich verstehe nicht, warum es * nicht *, aber ich weiß es nicht. –

+0

Ich bin bereit, Visual C++ bei Bedarf zu verwenden, aber ich bin nur froh, dass dies möglich ist. Ich lese noch einmal, wie 'dllimport' funktioniert, weil ich beim letzten Mal etwas falsch verstanden habe. – Vortico

Antwort

2

Ich habe herausgefunden, wie man es mit MinGW macht.

Normalerweise, wenn DLL-Dateien verknüpft (z plugin.dll), exportieren Sie eine Liste von Symbolen zu libplugin.a, aber in diesem Fall mag ich eigentlich die Symbole aus dem Host ausführbaren host.exe-libhost.a exportieren.

x86_64-w64-mingw32-g++ -o host.exe host.cpp -Wl,--out-implib,libhost.a

Dies erzeugt die Symbolliste, die Sie verknüpfen können, wenn Ihr Plugin zu bauen.

x86_64-w64-mingw32-g++ -shared -o plugin.dll plugin.cpp -L. -lhost

Dies baut die DLL die libhost.a-Datei (im aktuellen Verzeichnis "").

Jetzt ist es ein wenig nervig, Ihren Host-Code mit __declspec(dllexport) zu füllen, so dass Sie die --export-all-symbols Linker-Flag hinzufügen können. Und aus irgendeinem Grund scheint es keine _declspec(dllimport) Attribute zu erfordern, nachdem ich das getan habe, aber ich weiß nicht warum. So können Sie den Host mit

x86_64-w64-mingw32-g++ -o host.exe host.cpp -Wl,--export-all-symbols,--out-implib,libhost.a

+0

Siehe http://stackoverflow.com/a/4490536/886887, das '__declspec (dllimport)' ist nicht erforderlich, ermöglicht dem Linker jedoch, die Aufrufe zu optimieren. (Obwohl MinGW kompiliert und verknüpft in einem einzigen Befehl, vielleicht erhalten Sie auch die Optimierung kostenlos.) –

+0

Zum Vorteil der zukünftigen Leser, beachten Sie, dass die (mögliche) Nachteil für den Export aller Symbole anstelle von bestimmten bedeutet, dass es bedeutet Ein Plugin eines Drittanbieters könnte ein internes Symbol oder eine interne Funktion verwenden, die Sie nicht zur Verfügung stellen wollten, wodurch Kompatibilitätsprobleme in der Spur entstehen können. Wenn Sie nur mit Ihrem eigenen Code arbeiten, ist das egal - obwohl es in diesem Fall normalerweise einfacher ist, statische Verknüpfungen zu verwenden, als überhaupt eine DLL zu haben. –

+0

Es ist eine gute Lösung. Aber ich denke wirklich, der Weg für Windows mit Mingw eine DLL zu bauen ist hässlich. – Jimmy