Je rencontre des problèmes de liaison dans MSVC pour un projet que j'ai écrit pour g ++. Voici le problème:
Je construis libssh en tant que bibliothèque statique dans le cadre de mon application, en ajoutant la cible dans cmake avec
add_library (ssh_static STATIC $ libssh_SRCS)
Libssh est en C, j'ai donc 'extern "C" {...}' encapsulant les includes dans mes sources c ++. Je lie ensuite la cible ssh_static à mon exécutable, sshconnectiontest, avec
target_link_libraries (sshconnectiontest ... ssh_static ...)
Tout cela fonctionne très bien sous Linux avec gcc, mais maintenant sous MSVC je reçois
error LNK2019: unresolved external symbol __imp__[function names here] referenced in [filename]
pour chaque fonction libssh que j'utilise.
Des idées qui ne vont pas? J'ai lu quelque part que le préfixe imp signifie que l'éditeur de liens s'attend à lier un fichier .dll, mais cela ne devrait pas être le cas puisque ssh_static est déclaré bibliothèque statique dans l'appel add_library ...
D'après mes souvenirs de l'époque de Windows, dans les DLL construites par MinGW, le préfixe du symbole __imp__
est utilisé pour la fonction de trampoline qui appelle la DLL proprement dite. Ce symbole est alors fourni par une petite bibliothèque statique portant l'extension .dll.a
.
Lorsque vous incluez des en-têtes libssh, vous devez définir un #define
pour indiquer que vous envisagez de créer un lien statique. Si vous ne le faites pas, les fonctions libssh dans l'en-tête seront déclarées __declspec(dllimport)
et les symboles __imp__
seront donc attendus au moment de la liaison.
J'ai jeté un coup d'œil à la source libssh et je l'ai trouvé en haut de libssh.h
:
#ifdef LIBSSH_STATIC
#define LIBSSH_API
#else
#if defined _WIN32 || defined __CYGWIN__
#ifdef LIBSSH_EXPORTS
#ifdef __GNUC__
#define LIBSSH_API __attribute__((dllexport))
#else
#define LIBSSH_API __declspec(dllexport)
#endif
#else
#ifdef __GNUC__
#define LIBSSH_API __attribute__((dllimport))
#else
#define LIBSSH_API __declspec(dllimport)
#endif
#endif
#else
#if __GNUC__ >= 4
#define LIBSSH_API __attribute__((visibility("default")))
#else
#define LIBSSH_API
#endif
#endif
#endif
Vous devez définir LIBSSH_STATIC
, soit par #define
avant la ligne #include <libssh.h>
, soit en tant qu'option /D
. Puisque vous utilisez CMake, vous le ferez probablement par add_definitions
dans CMakeLists.txt
.
Je ne sais pas si c'est votre cas, mais le préfixe imp peut signifier que vous compilez une bibliothèque x64 dans un projet Win32.
Un peu tard pour la soirée, mais j'ai eu la même erreur lors du mélange de bibliothèques avec des liaisons statiques et dynamiques vers le tube cathodique
Utiliser un fichier .DEF
Si vous choisissez d'utiliser __declspec (dllimport) avec un fichier .DEF, vous devez modifier le fichier .DEF afin qu'il utilise DATA ou CONSTANT afin de réduire le risque qu'un code incorrect ne soit à l'origine d'un problème:
// project.def
LIBRARY project
EXPORTS
ulDataInDll CONSTANT
Le tableau suivant montre pourquoi:
Keyword Emits in the import library Exports
CONSTANT _imp_ulDataInDll _ulDataInDll
_ulDataInDll
DATA _imp_ulDataInDll _ulDataInDll
http://msdn.Microsoft.com/en-us/library/aa271769(v=vs.60).aspx
MAIS CONSTANT est maintenant obsolète
j'ai trouvé un autre moyen, dans le fichier .DEF d'utilisation .lib exporté:
mainthreadid=_mainthreadid
et regénérer la lib avec LIB.exe
dans le fichier d'en-tête d'importation du code dll ...
extern "C" {
extern const __declspec(dllexport) ulong mainthreadid;
}