【问题标题】:protocol buffers + zlib = unresolved external symbol协议缓冲区 + zlib = 未解析的外部符号
【发布时间】:2013-09-18 04:37:16
【问题描述】:

我的程序 (VS 2010) 使用启用了HAVE_ZLIB 选项编译的 Google 缓冲区协议。我编译了最新版本的zlib 并在我的项目中添加了.lib,但是在链接过程中我仍然得到了

1>libprotobuf.lib(gzip_stream.obj):错误 LNK2001:未解决 外部符号 _inflateEnd 1>libprotobuf.lib(gzip_stream.obj):错误 LNK2001:未解析的外部符号 inflateInit2 1>libprotobuf.lib(gzip_stream.obj):错误 LNK2001:未解决 外部符号 _inflate 1>libprotobuf.lib(gzip_stream.obj):错误 LNK2001:未解析的外部符号 deflateInit2 1>libprotobuf.lib(gzip_stream.obj):错误 LNK2001:未解决 外部符号 _deflate 1>libprotobuf.lib(gzip_stream.obj):错误 LNK2001:未解析的外部符号 _deflateEnd

我用dumpbin.exe /all zlib.lib,上面写着:

文件类型:图书馆

....

245 public symbols

....

 4DBE __imp__inflateInit2_@16
 4DBE _inflateInit2_@16

此列表中还有其他未解析的符号。

那怎么了?为什么链接器找不到这些函数?

upd:重新编译后zlib现在是__imp__inflateInit2_@4

【问题讨论】:

  • 在构建 zlib 时,您似乎已将__stdcall 设置为默认调用约定(可能使用/Gz 编译器开关),而调用代码需要旧的__cdecl
  • @Igor Tandetnik:刚刚检查了设置,那里是__cdecl,命令行参数中没有/Gz选项
  • dumpbin 另有说明。 @16 是 stdcall 名称修改的标志。另一件要检查的事情:也许函数被声明为void ZLIBAPI inflateEnd(...),而宏ZLIBAPI最终在一个地方扩展为__stdcall,但在另一个地方扩展为__cdecl
  • @IgorTandetnik:从我看到的代码来看,它编译为 __cdecl。 Ш 重新编译它,现在dumpbin.exe 说_inflateEnd@4,而不是@16
  • 您之前查看的是inflateInit2,而不是inflateEnd。 @符号后面的数字是所有函数参数所需的总字节数,所以对于不同的函数自然可能会有所不同。同样,这就是 __stdcall 名称修饰的工作方式(参见 this document 的“名称修饰”部分)

标签: c++ visual-c++ linker zlib unresolved-external


【解决方案1】:

zlib 函数被定义为 ZEXPORT。 如果定义了 ZLIB_WINAPI,则 ZEXPORT 定义为 __stdcall,否则没有值,所有 zlib 函数默认定义为 __cdecl。

当我在VS2015中编译zlib时,ZLIB_WINAPI是在zlib项目中定义的,而在我的c++项目中ZLIB_WINAPI是没有定义的。 所以我的项目是在zlib.lib文件中寻找__cdecl函数,zlib.lib文件编译为__stdcall。

要解决这个问题,您需要告诉项目中的编译器 zlib .lib 文件使用 __stdcall 调用约定。

使用:

#define ZLIB_WINAPI

之前

#include "....\zlib.h"

在你的项目中

【讨论】:

  • 虽然这个答案可能是正确的,但请添加一些解释。传递底层逻辑比仅仅提供代码更重要,因为它可以帮助 OP 和其他读者自己解决这个问题和类似问题。
  • @JasonMc92 我加了解释
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 2021-12-19
  • 2011-11-15
  • 1970-01-01
相关资源
最近更新 更多