2009-01-14 8 views
7

Ich habe eine Anwendung und mehrere Plugins in DLL-Dateien. Die Plugins verwenden Symbole aus der Anwendung über eine Exportbibliothek. Die Anwendung verbindet sich in mehreren statischen Bibliotheken und hier stammen die meisten Symbole. Dies funktioniert gut, solange die Anwendung ein Symbol verwendet. Wenn das Symbol dort nicht verwendet wird, erhalte ich Linker-Fehler beim Kompilieren der DLL.Forcing Symbol Export mit MSVC

Wie kann ich den Export der Symbole erzwingen, die nur in den Plugins verwendet werden?

Um den Export zu triggern ich so etwas wie dies versucht haben:

class MyClassExporter 
    { 
     MyClass mInstance; 
    public: 
     MyClassExporter() {} 
    }; 
    static MyClassExporter TheMyClassExporter; 

in einem der statischen Libs die Anwendung zu zwingen, den Export hergestellt, die nicht funktioniert hat.

Als Antwort auf Greg (danke für die Antwort) und um zu verdeutlichen: Die Klasse, für die ich den Export erzwingen möchte, ist MyClass (welches __declspec (...) definiert hat, abhängig davon, ob ich exportieren oder importieren möchte) . MyClassExport war mein Versuch, die Aufnahme von (in Bezug auf die Anwendung) unbenutzten Symbolen in die App zu erzwingen. Ich möchte die Symbole "anfassen", damit der Linker sie als gebraucht erkennt und in die Anwendung einfügt, damit sie diese wiederum in meine Plugins exportieren kann. Das Verknüpfen der statischen Bibliotheken in den Plugins ist keine Option, da sie Singletons enthalten, die dupliziert werden würden (App und DLLs haben jeweils ihre eigene Kopie statischer Variablen).

Antwort

3

Sie wollen wahrscheinlich bei __declspec (Export/Import) suchen

#ifdef DLL_EXPORTING 
#define WHDLL __declspec(dllexport) 
#else 
#define WHDLL __declspec(dllimport) 
#endif 

Wenn statischen Modul in eine DLL-Verknüpfung wird es nur in dem Code bringen, die verwendet wird. Ich habe nie Sachen von einer statischen Bibliothek importiert, um sie einfach wieder zu exportieren.
Vielleicht müssen Sie es nur als exportierbar in der DLL beim Kompilieren der statischen Lib markieren.

Aber das erinnert mich an das Einfügen von Std-Containern in exportierte Klassen und einige Tricks in msvc, um die 'Instanz' des spezialisierten Containers zu exportieren. der Template-Code ist ähnlich wie Ihr statischen Code (in meinem Denken)

zum Beispiel ohne die Vorlage, die Sie Warnungen des Template-Code erhalten wird, um die Klasse nicht exportiert zu unterstützen - das ist MSVC spezifisch aus meinem Verständnis

template class DLL_EXPORTING std::auto_ptr<wxCursor>; 
class DLL_EXPORTING imageButton : public wxWindow 
{ 
    std::auto_ptr<wxCursor> m_Cursor; 
}; 
+0

Ich muss aus den statischen Bibliotheken und den Export in die Plugins importieren, weil ich Singletons in ihnen haben, die dupliziert bekommen würde, wenn ich sie in das DLL verknüpfen würde (DLLs und App ihre eigene statische Variablen). Dein erster Satz erklärt das Problem: Ich suche nach einer Möglichkeit, die Aufnahme zu erzwingen. – torque

4

Die Direktive /INCLUDE kann verwendet werden, um den MSVC-Linker zum Einfügen eines Symbols zu zwingen. Alternativ kann /OPT:NOREF verwendet werden, um das Entfernen nicht verwendeter Symbole im Allgemeinen zu deaktivieren.

Ein gängiger Ansatz besteht darin, eine einzelne nicht verwendete Funktion zu erstellen, die auf alle für Ihre Plugins exportierten Objekte verweist. Dann brauchen Sie nur eine einzelne/INCLUDE-Direktive für diese Funktion.

+0

Ausprobiert, aber nicht funktioniert - sollen die Symbole "dekoriert" werden? Können sie Namespaces enthalten? – xtofl

+0

Hat es mit/OPT funktioniert: NOREF? Wenn nicht, können Sie ein anderes Problem insgesamt haben ... –

+0

Symbole in ihrer eingerichteten Form angegeben werden –

2

Was ich versuchte zu lösen dies war:

  1. build eine statische Bibliothek mit Funktion void afunction(int).
  2. Erstellen Sie eine DLL, verknüpft mit statischen Lib, Exportieren afunction.
  3. Erstellen Sie eine EXE mit dem afunction Symbol.

Wie?Da der Linker an Exportfunktionen gesagt werden kann, die __declspec(dllexport) Richtlinie verwenden, muss eine DLL nicht mehr als ein erklären thusly zu-Symbol exportiert.

LIB hat einen Header „afunction.h“ und eine begleitende CPP-Datei der Funktionskörper enthält:

// stat/afunction.h 
namespace static_lib { void afunction(int); } 


// stat/afunction.cpp 
#include "afunction.h" 
namespace static_lib { void afunction(int){ } } 

Die DLL hat eine Include-Datei „indirect.h“, die Erklärung der Funktion enthält, exportiert werden. Die DLL hat eine Link-Zeit-Abhängigkeit von der statischen lib. (Linker-Optionen: Input/zusätzliche Abhängigkeiten: "static_library.lib")

// dll/indirect.h 
namespace static_lib { 
    __declspec(dllexport) void afunction(int); 
} 

Die ausführbare Datei hat nur die indirekt Datei enthalten:

#include <dll/indirect.h> 
int main() { static_lib::afunction(1); } 

Und wissen Sie was? Es kompiliert, verbindet und sogar läuft!

1

Es gibt einige Diskussion dieses Problems auf MSDN, die recht nützlich war. Wie sich herausstellt, ist/OPT: NOREF in diesem Fall nicht besonders hilfreich./INCLUDE kann funktionieren, aber es kann schwierig sein, automatisch herauszufinden, was/INCLUDE sein muss. Es gibt leider keine Silberkugel.

http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/2aa2e1b7-6677-4986-99cc-62f463c94ef3

+0

dieser Thread die Antwort hatte, aber es war nicht klar, und es gab einen irreführenden Kommentar angibt, das nicht mit VS2005 funktioniert, wenn es tatsächlich ist. Siehe meine Antwort auf diese SO Frage für Details ... –

2

Die "Use Bibliothek Abhängigkeit Eingänge" Option funktioniert der Trick in VS2005! > Linker - -> Allgemein -> Benutzung Bibliothek Abhängigkeit Eingänge

Diese Option kann unter Konfigurationseigenschaften finden. Auf "true" setzen, um das Verknüpfen in ALLE Symbole & Code zu erzwingen, der in jeder LIB deklariert ist, die als Eingabe für das Projekt angegeben wurde.

Sie können das Symbol folgende zu erhalten tun aus dem DLL zu exportieren: definieren LIB_EXPORTS in der Bibliothek Projekt und nichts entweder in dem DLL-Projekt oder das DLL-Client-Projekt.

#ifdef LIB_EXPORTS 
#define DLLAPI __declspec(dllexport) 
#else 
#define DLLAPI __declspec(dllimport) 
#endif 

stellte sich heraus, gibt es keine Notwendigkeit #include irgendwelche Header aus dem LIB-Projekt, wenn das DLL-Projekt kompilieren; Gib einfach die LIB als Linker-Eingabe an. Wenn Sie jedoch den LIB-Code innerhalb der DLL verwenden müssen, müssen Sie DLLAPI als leeres Makro definieren. Das Setzen der Symbole auf dllexport oder dllimport erzeugt jeweils einen Fehler oder eine Warnung.