Lier LNK2019 d'erreur dans MSVC, symboles non résolus avec __imp__ préfixe, mais devrait être de lib statique
-
02-10-2019 - |
Question
Je suis en cours d'exécution en reliant des problèmes à MSVC pour un projet que j'ai écrit pour g ++. Voici le problème:
Je construis libssh comme une bibliothèque statique dans le cadre de ma demande, en ajoutant la cible dans CMake avec
add_library (ssh_static STATIC $ libssh_SRCS)
libssh est en C, donc je 'extern "C" {...}' enveloppant le comprend dans mes c ++ sources. Je vous redirigent 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 je reçois MSVC
error LNK2019: unresolved external symbol __imp__[function names here] referenced in [filename]
pour toutes les fonctions libssh-je utiliser.
Toutes les idées ce qui se passe mal? Je l'ai lu quelque part que le diablotin des moyens préfixe l'éditeur de liens ATTEND pour lier un .dll, mais cela ne devrait pas être le cas puisque ssh_static est déclaré une bibliothèque statique dans l'appel add_library ...
La solution
D'après ce que je me souviens de mes jours de Windows, dans les DLL construites MinGW, le préfixe symbole __imp__
est utilisé pour la fonction de trampoline que les appels dans la DLL appropriée. Ce symbole est alors fourni par une petite bibliothèque statique avec l'extension .dll.a
.
Lorsque vous incluez les en-têtes libssh, vous devez définir un #define
pour indiquer que vous vous attendez à un lien statique. Si vous ne le faites pas, les fonctions de libssh dans l'en-tête seront déclarés __declspec(dllimport)
et donc les symboles __imp__
seront attendus au moment de la liaison.
J'ai eu un coup d'oeil à la source de libssh et trouvé ce 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 de #include <libssh.h>
, ou en option /D
. Puisque vous utilisez CMake, vous allez probablement faire cela par add_definitions
dans CMakeLists.txt
.
Autres conseils
Je ne sais pas si elle est votre cas, mais le préfixe diablotin peut signifier que vous compilez une bibliothèque x64 dans un projet Win32.
Un peu tard pour le parti, mais je suis la même erreur lors du mélange des bibliothèques avec une liaison statique et dynamique du CRT
L'utilisation d'un fichier .def
Si vous choisissez d'utiliser __declspec (dllimport) avec un fichier .def, vous devez modifier le fichier .def d'utiliser les données ou CONSTANT pour réduire la probabilité que le codage incorrect provoquera un problème:
// project.def
LIBRARY project
EXPORTS
ulDataInDll CONSTANT
Le tableau ci-dessous 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
et CONSTANT est maintenant désapprouvée
je l'ai trouvé une autre façon, dans le fichier .def d'utilisation .lib exporté:
mainthreadid=_mainthreadid
et régénérer le répertoire lib avec lib.exe
dans le fichier d'en-tête d'importation du code dll ...
extern "C" {
extern const __declspec(dllexport) ulong mainthreadid;
}