Si vous voulez des exportations C simples, utilisez un projet C et non C ++. Les DLL C ++ reposent sur la gestion des noms pour tous les ismes C ++ (espaces de noms, etc.). Vous pouvez compiler votre code en C en allant dans les paramètres de votre projet sous C / C ++ -> Avancé, il existe une option "Compiler en tant que" qui correspond aux commutateurs du compilateur / TP et / TC.
Si vous souhaitez toujours utiliser C ++ pour écrire les éléments internes de votre bibliothèque, mais exporter certaines fonctions démêlées pour une utilisation en dehors de C ++, consultez la deuxième section ci-dessous.
Exportation / importation de bibliothèques DLL dans VC ++
Ce que vous voulez vraiment faire est de définir une macro conditionnelle dans un en-tête qui sera inclus dans tous les fichiers source de votre projet DLL:
#ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
#else
# define LIBRARY_API __declspec(dllimport)
#endif
Ensuite, sur une fonction que vous souhaitez exporter vous utilisez LIBRARY_API
:
LIBRARY_API int GetCoolInteger();
Dans votre projet de construction de bibliothèque, créez une définition, LIBRARY_EXPORTS
cela entraînera l'exportation de vos fonctions pour votre construction DLL.
Puisque LIBRARY_EXPORTS
ne sera pas défini dans un projet utilisant la DLL, lorsque ce projet inclut le fichier d'en-tête de votre bibliothèque, toutes les fonctions seront importées à la place.
Si votre bibliothèque doit être multiplateforme, vous pouvez définir LIBRARY_API comme rien si vous n'êtes pas sous Windows:
#ifdef _WIN32
# ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
# else
# define LIBRARY_API __declspec(dllimport)
# endif
#elif
# define LIBRARY_API
#endif
Lorsque vous utilisez dllexport / dllimport, vous n'avez pas besoin d'utiliser des fichiers DEF, si vous utilisez des fichiers DEF, vous n'avez pas besoin d'utiliser dllexport / dllimport. Les deux méthodes accomplissent la même tâche de différentes manières, je crois que dllexport / dllimport est la méthode recommandée parmi les deux.
Exportation de fonctions démêlées à partir d'une DLL C ++ pour LoadLibrary / PInvoke
Si vous en avez besoin pour utiliser LoadLibrary et GetProcAddress, ou peut-être pour importer à partir d'un autre langage (par exemple PInvoke de .NET, ou FFI en Python / R, etc.), vous pouvez utiliser en extern "C"
ligne avec votre dllexport pour dire au compilateur C ++ de ne pas modifier les noms. Et puisque nous utilisons GetProcAddress au lieu de dllimport, nous n'avons pas besoin de faire la danse ifdef d'en haut, juste un simple dllexport:
Le 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())
);
}
Et voici à quoi ressemblent les exportations avec Dumpbin / exports:
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)
Donc, ce code fonctionne bien:
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
supprimera la décoration qui décrit les types de paramètres de la fonction, mais pas la décoration qui décrit la convention d'appel de la fonction; b) pour supprimer toute décoration, vous devez spécifier le nom (non décoré) dans un fichier DEF.