Ошибка связывания LNK2019 в MSVC, неразрешенные символы с префиксом __imp__, но должны быть из статической библиотеки - PullRequest
25 голосов
/ 14 сентября 2010

Я сталкиваюсь с проблемами связывания в MSVC для проекта, который я написал для g ++.Вот проблема:

Я создаю libssh как статическую библиотеку как часть моего приложения, добавляя цель в cmake с помощью

add_library (ssh_static STATIC $ libssh_SRCS)

Libssh isв C, поэтому у меня есть 'extern "C" {...}', включающий включения в мои исходные коды на c ++.Затем я связываю цель ssh_static с моим исполняемым файлом sshconnectiontest с помощью

target_link_libraries (sshconnectiontest ... ssh_static ...)

Все это прекрасно работает в linux с gcc, но теперь в MSVC Iполучить

error LNK2019: unresolved external symbol __imp__[function names here] referenced in [filename]

для каждой используемой мной функции libssh.

Есть идеи, что происходит не так?Я где-то читал, что префикс imp означает, что компоновщик ожидает связать .dll, но это не должно иметь место, поскольку ssh_static объявляется статической библиотекой в ​​вызове add_library ...

Ответы [ 4 ]

28 голосов
/ 15 сентября 2010

Из того, что я помню о своих днях в Windows, в библиотеках, построенных на MinGW, префикс символа __imp__ используется для функции батута, которая вызывает саму DLL. Этот символ затем предоставляется небольшой статической библиотекой с расширением .dll.a.

Когда вы включаете заголовки libssh, вам нужно установить #define, чтобы указать, что вы ожидаете статической ссылки. Если вы этого не сделаете, функции libssh в заголовке будут объявлены __declspec(dllimport), и поэтому символы __imp__ ожидаются во время ссылки.

Я посмотрел на источник libssh и нашел его в верхней части 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

Вам необходимо определить LIBSSH_STATIC либо через #define перед строкой #include <libssh.h>, либо как параметр /D. Поскольку вы используете CMake, вы, вероятно, сделаете это через add_definitions в CMakeLists.txt.

13 голосов
/ 05 мая 2011

Не знаю, так ли это, но префикс imp может означать, что вы компилируете библиотеку x64 в проекте Win32.

1 голос
/ 10 мая 2017

Несколько опоздал на вечеринку, но я получил ту же ошибку при смешении библиотек со статической и динамической связью с CRT

0 голосов
/ 06 августа 2011

Использование файла .DEF

Если вы решите использовать __declspec (dllimport) вместе с файлом .DEF, вам следует изменить файл .DEF на использование DATA или CONSTANT, чтобы уменьшить вероятность того, что неправильное кодирование вызовет проблему:

// project.def
LIBRARY project
EXPORTS
   ulDataInDll   CONSTANT

Следующая таблица показывает, почему:

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

НО CONSTANT устарел

я нашел другой путь, в файле .DEF экспортированного использования .lib:

 mainthreadid=_mainthreadid

и восстановить библиотеку с помощью LIB.exe

в заголовочном файле импорта кода dll ...

extern "C" {
  extern const __declspec(dllexport) ulong mainthreadid;
}
...