MSVC 中的链接错误 LNK2019,带有 __imp__ 前缀的未解析符号,但应该来自静态库

Posted

技术标签:

【中文标题】MSVC 中的链接错误 LNK2019,带有 __imp__ 前缀的未解析符号,但应该来自静态库【英文标题】:Linking error LNK2019 in MSVC, unresolved symbols with __imp__ prefix, but should be from static lib 【发布时间】:2011-04-11 21:18:35 【问题描述】:

对于我为 g++ 编写的项目,我在 MSVC 中遇到了链接问题。问题来了:

我将 libssh 构建为静态库作为我的应用程序的一部分,在 cmake 中添加目标

add_library(ssh_static STATIC $libssh_SRCS)

Libssh 是用 C 语言编写的,所以我有 'extern "C" ...' 将包含在我的 c++ 源代码中。然后,我使用

将 ssh_static 目标链接到我的可执行文件 sshconnectiontest

target_link_libraries(sshconnectiontest ... ssh_static ...)

这在 linux 中使用 gcc 一切正常,但现在在 MSVC 中我得到了

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

对于我使用的每个 libssh 函数。

任何想法出了什么问题?我在某处读到 imp 前缀意味着链接器期望链接一个 .dll,但情况并非如此,因为 ssh_static 在 add_library 调用中被声明为静态库...

【问题讨论】:

【参考方案1】:

根据我对 Windows 日子的记忆,在 MinGW 构建的 DLL 中,__imp__ 符号前缀用于调用 DLL 的 trampoline 函数。然后这个符号由一个扩展名为 .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

您需要在#include <libssh.h> 行之前通过#define 定义LIBSSH_STATIC,或者作为/D 选项定义。由于您使用的是 CMake,因此您可能会通过 add_definitions in CMakeLists.txt 执行此操作。

【讨论】:

做到了 :-) 我在编译 libssh 时设置了标志,但没有为其他项目设置标志。谢谢! 黄金答案!帮了我很多忙。【参考方案2】:

不知道是不是你的情况,但是imp前缀可能意味着你正在Win32项目中编译x64库。

【讨论】:

这实际上是我在 Windows 上的问题。我无意中将 64 位 dll 与 32 位 dll 链接。 如果你选择了“在静态库中使用 MFC”选项是错误的,你会得到错误。【参考方案3】:

聚会有点晚了,但在将库与 CRT 的静态和动态链接混合时遇到了同样的错误

【讨论】:

【参考方案4】:

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

我找到了另一种方法,在导出的 .lib 的 .DEF 文件中使用:

 mainthreadid=_mainthreadid

并使用 LIB.exe 重新生成库

在dll代码的导入头文件中...

extern "C" 
  extern const __declspec(dllexport) ulong mainthreadid;

【讨论】:

以上是关于MSVC 中的链接错误 LNK2019,带有 __imp__ 前缀的未解析符号,但应该来自静态库的主要内容,如果未能解决你的问题,请参考以下文章

了解 Visual Studio 2010 中的此错误 (LNK 2019)

编译dll但出现错误LNK2019

Error:LNK2019无法解析的外部符号_sscanf, _vsprintf

只有 wWinMain MSVC 2019 的链接器错误无法解析外部符号

dcmtk lnk2019 无法解析外部符号

如何解决 LNK2019 未解决的外部 __imp____iob_func