2012-04-09 12 views
0

Ich versuche, eine hypothetische Plugin mit dem folgenden Header zu laden:Warum kann ich eine C++ statische Klassen-Factory-Methode in einer DLL mit GetProcAddress nicht aufrufen?

#ifndef _DLL_H_ 
#define _DLL_H_ 

#if BUILDING_DLL 
# define DLLIMPORT __declspec (dllexport) 
#else /* Not BUILDING_DLL */ 
# define DLLIMPORT __declspec (dllimport) 
#endif /* Not BUILDING_DLL */ 


class DLLIMPORT DllClass 
{ 

    public: 

    virtual ~DllClass(void); 
    static DllClass* getPCFilter(); 
    virtual int Process(int a, int b); 

    protected: 

    DllClass(); 
}; 


#endif /* _DLL_H_ */ 

Und mein Host Code tut:

HINSTANCE hinstDLL; 
hinstDLL = LoadLibrary(L"PCFilter.dll"); 

if(hinstDLL) 
{ 
    typedef DllClass*(*Factory)(); 
    Factory fun1; 

    fun1 = (Factory)GetProcAddress(hinstDLL, "DllClass::getPCFilter"); 

Die dll öffnet aber die GetProcAddress ist nicht die statische Factory-Methode zu finden. Soll ich das nicht so machen können?

Ich habe versucht, immer von der statischen Methode zu befreien und stattdessen nach der Klassendeklaration, die folgenden Aktionen ausführen:

extern "C" DLLIMPORT void* getPCFilterInstance() 
{ 
    return (void*)new DllClass(); 
} 

Aber dann, wenn die Host-Quelle kompilieren, der Linker klagt:

In function `getPCFilterInstance':: 
[Linker Error] undefined reference to `_imp___ZN8DllClassC1Ev' 

Das kann ich lösen, indem ich auf die .a lib verlinke. Aber ist es nicht die Idee der DLL, nicht zur Kompilierzeit verlinken zu müssen?

+0

mit vielleicht ein 'extern„C“' Funktion sollte Hilfe. –

+1

Der Funktionsname ist nicht "DLLClass :: getPCFilter". Schauen Sie sich die Export-Tabelle der DLL an. –

Antwort

1

Sie extern "C" Anweisung verwenden können Sie Ihre Funktion mit dem gleichen Namen zu exportieren, wie Sie es im Code deklariert haben - sonst wird es von der C++ Compiler

verstümmelt erhalten
+1

Zuerst ist falsch. Zweitens ist irreführend. –

+0

stimmte überein 1 (und entfernte es) – Bond

+0

Ich versuchte das, die Funktion sieht so aus: extern "C" DLLIMPORT void * getPCFilterInstance() { Rückkehr (void *) neues DllClass(); } und einen Linker-Fehler erhalten: [Linker Error] undefinierter Verweis auf '_imp___ZN8DllClassC1Ev ' – SaldaVonSchwartz

5

Sie ignorieren die Tatsache, dass der Funktionsname geschmückt wird ("name mangling") oder gar nicht sichtbar in der DLL-Schnittstelle (unter dem gegebenen Namen). Nach meinem Wissen GetProcAddress macht keinen Namen, aber der Linker tut dies (wenn eine DLL mit exportierten Klassen statisch importiert wird).

Best Practice ist meines Wissens eine Factory-Funktion zu liefern, die einen undecorated Namen und eine vordefinierte Aufrufkonvention hat, so wie COM es vorschreibt (siehe DllGetClassObject).

Hinweis: Ich sollte hinzufügen, dass je nach dem Compiler/Linker die verzierten ("gemangelt") Namen variieren. Verschiedene Compiler, andere Regeln. Daher sind sie unter Umständen nicht miteinander kompatibel, ohne dass es zu beträchtlichen Umbauten kommt.

Edit: über die Frage:

But isn't the idea of the DLL to not need to link at compile time?

Nun, ja und nein. Unter Windows ist der gesamte Prozess etwas anders als bei unixoiden Systemen. Der Loader kümmert sich um die Auflösung von Abhängigkeiten und so weiter, aber der Punkt ist, dass es zwei Möglichkeiten gibt, eine DLL zu laden. Eine davon ist das statische Importieren einer DLL, in diesem Fall wird die Namensauflösung durchgeführt, bevor das Programm ausgeführt wird (oder davor fehlschlägt), und die andere besteht darin, die DLL dynamisch mit LoadLibrary und Freunden zu laden und dann die Funktionsadresse mit GetProcAddress aufzulösen . Letzteres hat eine Variation (unterstützt vom Linker), die als Delay-Loading bezeichnet wird. Letztendlich ist es nur noch die zweite Methode.

Verzögerung-Laden bietet genau das, was Sie wollen, indem Sie den Linker kümmern sich um die Namen zu lösen und weiterhin Fehler beim Laden der DLL oder bei der Auflösung eines Namens zur Laufzeit behandeln können.

+0

Ich habe meine Frage bearbeitet: Ich habe den externen "C" -Funktionsansatz ausprobiert und trotzdem scheint es nicht sichtbar zu sein? – SaldaVonSchwartz

+0

@SaldaVonSchwartz: Was ist nicht sichtbar? Die (separate) Factory-Funktion oder die statische Member-Funktion? Auch "extern" C "beeinflusst meistens den Namen Mangling in diesem Fall, nicht die Sichtbarkeit als solche (meines Wissens). – 0xC0000022L

+0

Sie benötigen entweder eine '.def 'Datei oder verwenden Sie' __declspec (dllexport) 'dafür. – 0xC0000022L

Verwandte Themen