web-dev-qa-db-fra.com

Erreur de liaison LNK2019 dans MSVC, symboles non résolus avec le préfixe __imp__, mais devant provenir de la bibliothèque statique

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 ...

25
dlonie

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.

28
Jack Kelly

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.

13
Ago

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

1
kreuzerkrieg

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;
}
0
Tanguy