Wenn Sie einfache C-Exporte wünschen, verwenden Sie ein C-Projekt, nicht C ++. C ++ - DLLs basieren auf der Namensverwaltung für alle C ++ - Ismen (Namespaces usw.). Sie können Ihren Code als C kompilieren, indem Sie in Ihre Projekteinstellungen unter C / C ++ -> Erweitert gehen. Es gibt eine Option "Kompilieren als", die den Compiler-Schaltern / TP und / TC entspricht.
Wenn Sie weiterhin C ++ zum Schreiben der Interna Ihrer Bibliothek verwenden möchten, aber einige Funktionen exportieren möchten, die für die Verwendung außerhalb von C ++ nicht verwickelt sind, lesen Sie den zweiten Abschnitt unten.
Exportieren / Importieren von DLL-Bibliotheken in VC ++
Was Sie wirklich tun möchten, ist ein bedingtes Makro in einem Header zu definieren, das in allen Quelldateien Ihres DLL-Projekts enthalten ist:
#ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
#else
# define LIBRARY_API __declspec(dllimport)
#endif
Dann verwenden Sie für eine Funktion, die Sie exportieren möchten, Folgendes LIBRARY_API
:
LIBRARY_API int GetCoolInteger();
Erstellen Sie in Ihrem Bibliothekserstellungsprojekt eine Definition. Dadurch LIBRARY_EXPORTS
werden Ihre Funktionen für Ihren DLL-Build exportiert.
Da LIBRARY_EXPORTS
in einem Projekt, das die DLL verwendet, nicht definiert wird, werden stattdessen alle Funktionen importiert, wenn dieses Projekt die Header-Datei Ihrer Bibliothek enthält.
Wenn Ihre Bibliothek plattformübergreifend sein soll, können Sie LIBRARY_API als nichts definieren, wenn Sie nicht unter Windows arbeiten:
#ifdef _WIN32
# ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
# else
# define LIBRARY_API __declspec(dllimport)
# endif
#elif
# define LIBRARY_API
#endif
Wenn Sie dllexport / dllimport verwenden, müssen Sie keine DEF-Dateien verwenden. Wenn Sie DEF-Dateien verwenden, müssen Sie dllexport / dllimport nicht verwenden. Die beiden Methoden erfüllen dieselbe Aufgabe auf unterschiedliche Weise. Ich glaube, dass dllexport / dllimport die empfohlene Methode unter den beiden ist.
Exportieren nicht entwirrter Funktionen aus einer C ++ - DLL für LoadLibrary / PInvoke
Wenn Sie dies benötigen, um LoadLibrary und GetProcAddress zu verwenden oder möglicherweise aus einer anderen Sprache zu importieren (z. B. PInvoke aus .NET oder FFI in Python / R usw.), können Sie extern "C"
inline mit Ihrem dllexport den C ++ - Compiler anweisen, die Namen nicht zu entstellen. Und da wir GetProcAddress anstelle von dllimport verwenden, müssen wir den ifdef-Tanz nicht von oben ausführen, sondern nur einen einfachen dllexport:
Der Code:
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
EXTERN_DLL_EXPORT int getEngineVersion() {
return 1;
}
EXTERN_DLL_EXPORT void registerPlugin(Kernel &K) {
K.getGraphicsServer().addGraphicsDriver(
auto_ptr<GraphicsServer::GraphicsDriver>(new OpenGLGraphicsDriver())
);
}
Und so sehen die Exporte mit Dumpbin / Exporten aus:
Dump of file opengl_plugin.dll
File Type: DLL
Section contains the following exports for opengl_plugin.dll
00000000 characteristics
49866068 time date stamp Sun Feb 01 19:54:32 2009
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 0001110E getEngineVersion = @ILT+265(_getEngineVersion)
2 1 00011028 registerPlugin = @ILT+35(_registerPlugin)
Dieser Code funktioniert also einwandfrei:
m_hDLL = ::LoadLibrary(T"opengl_plugin.dll");
m_pfnGetEngineVersion = reinterpret_cast<fnGetEngineVersion *>(
::GetProcAddress(m_hDLL, "getEngineVersion")
);
m_pfnRegisterPlugin = reinterpret_cast<fnRegisterPlugin *>(
::GetProcAddress(m_hDLL, "registerPlugin")
);
extern C
die Dekoration entfernt wird, die die Parametertypen der Funktion beschreibt, aber nicht die Dekoration, die die Aufrufkonvention der Funktion beschreibt; b) Um alle Dekorationen zu entfernen , müssen Sie den (nicht dekorierten) Namen in einer DEF-Datei angeben.