2010-08-26 13 views
9

dll Export-HeaderEine Warnung mit dem Bau 64-Bit-DLL

extern "C" 
void _declspec(dllexport) __stdcall foo(); 

DEF-Datei

EXPORTS 
foo   @1 

Wenn ich die dll von 64-Bit-Build-Konfiguration aufbauen, treffe ich diese Warnung.

Warnung LNK4197: export 'foo' mehrmals angegeben; unter Verwendung der ersten Spezifikation

Aber wenn ich die DLL durch 32bit Build-Konfiguration erstellen, tritt die Warnung nie auf.
Was ist das Problem? Was ist der Unterschied.

In DLL-Header für Interface verwenden wir in der Regel diese Technik,

#ifdef EXPORT_DLL 
#define BASICAPI _declspec(dllexport) 
#else 
#define BASICAPI _declspec(dllimport) 
#endif //_EXPORT_DLL 

Aber wenn def Datei auch vorhanden ist, werden wir immer die Warnung treffen, wenn wir 64-Bit-DLL bauen.
Also, sollten wir die Codes so schreiben?

#ifdef EXPORT_DLL 
#define BASICAPI 
#else 
#define BASICAPI _declspec(dllimport) 
#endif //_EXPORT_DLL 

Es funktioniert gut. Aber es ist mir nicht bekannt.
Geben Sie mir Ihre Meinung.

Antwort

11

Es ist im Allgemeinen nicht empfehlenswert, Exporte für dieselbe Funktion zweimal anzugeben. Wenn Sie bereits __declspec(dllexport) haben, müssen Sie den Export auch nicht in einer .def-Datei angeben. Umgekehrt, wenn Sie den Export in einer .def-Datei aufgelistet haben, brauchen Sie keine __declspec(dllexport).

ich glaube, der Grund für die Warnung ist, dass in x86-Builds, die __declspec(dllexport) ist die ergänzten Namen mit einem Unterstrich zu exportieren, aber die 64-Bit-Compiler dekorieren nicht Namen mit einem Unterstrich, auf das Duplikat führt. Um dies zu überprüfen, können Sie sich die 32-Bit-DLL in Dependency Walker ansehen, und Sie sollten zwei exportierte Funktionen sehen, "foo" und "_foo".

+2

'64-Bit-Compiler schmückt nicht Namen 'Ich wusste das nicht. Das war der Grund! Vielen Dank. – Benjamin

+0

Übrigens, wie kann ich Kursivschrift im Kommentarfeld verwenden. – Benjamin

+0

Es * schmückt * Namen, es schmückt sie nur anders als der 32-Bit-Compiler (d. H. Ohne den führenden Unterstrich). Sie können eine Funktion zweimal mit verschiedenen Namen exportieren (das ist, was ich in Ihren 32-Bit-Builds erwarte). Die Warnung liegt darin, dass bei 64-Bit-Builds sowohl die '__declspec'- als auch die .def-Datei zu dem * selben * Ergebnis führen würden. exportierter Name - einer von ihnen gilt als redundant. –

5

__declspec(dllexport) und .def-Dateien sind zwei verschiedene Möglichkeiten, Symbole aus einer DLL zu exportieren. Du brauchst beide nicht und solltest eines von ihnen weglassen. Die __declspec-Methode ist viel vielseitiger für C++ - Programme, da sie Namen mit C++ Mangling exportiert, so dass überladene Funktionen exportiert werden können, aber umgekehrt erschwert dies den Import der Namen über GetProcAddress.

Auch ist die Verwendung eines generischen Makros wie EXPORT_DLL gefährlich, da es bedeutet, dass Sie keine DLL erstellen können, die eine andere DLL verwendet, ohne die eine DLL versucht, alle Symbole beider DLLs zu exportieren.

DevStudio erstellt automatisch ein Symbol auf DLL-Projekten: <PROJECT>_EXPORTS es einfach und sicher macht einen EXPORT Makro zu erstellen:

#ifdef EXPORT 
#undef EXPORT 
#endif 
#ifdef PROJECTNAMEHERE_EXPORTS 
#define EXPORT __declspec(dllexport) 
#else 
#define EXPORT __declspec(dllimport) 
#endif 

EXTERN_C EXPORT void __stdcall Function1(void); 
EXTERN_C EXPORT void __cdecl Function2(...); 
     EXPORT void Function3(void); 

Funktionen 1 & 2 können mit GetProcAddress als [email protected] und Function2 jeweils geholt werden. Function3 wird über einen compilerspezifischen Mangled-Namen exportiert, der ungefähr so ​​aussieht: @[email protected]@[email protected]. Dieser Name unterscheidet sich für jede Überladung der Funktion, so dass Überlastung möglich ist.

Es ist wichtig, den Namen Mangeln von __declspec als def Dateien wissen, ist es egal, und würde exportieren nur Function1, Function2 und Function3.

+1

Ihr erster Absatz ist ziemlich genau das, was ich mit * meinem * ersten Absatz sagen wollte, aber Sie sagten es viel besser als ich, +1 :) –

+0

Schöne Antwort und Kommentar. +1 :) – Benjamin

+0

Ich wusste nicht über die 64-Bit-Sache. –