为什么我的 C++ 符号名称与我链接到的 libtorrent 库不同,这是否会导致链接失败?

Why is my C++ symbol name different from the libtorrent library I'm linking to and does this cause linking to fail?

提问人:Ragesh 提问时间:2/8/2023 最后编辑:Ragesh 更新时间:2/9/2023 访问量:133

问:

我正在尝试将一个简单的 C++ 程序链接到:libtorrent

#include <libtorrent/add_torrent_params.hpp>
#include <libtorrent/magnet_uri.hpp>

int main(int argc, char const* argv[])
{
    lt::add_torrent_params atp = lt::parse_magnet_uri(argv[1]);
}

我在命令行上调用,它告诉我我有未解析的外部符号:cl.exe

>cl /EHsc /Fefoo.exe /I<snip>\vcpkg\installed\x86-windows\include main.cpp torrent-rasterbar.lib /link /LIBPATH:<snip>\vcpkg\installed\x86-windows\lib
Microsoft (R) C/C++ Optimizing Compiler Version 19.34.31937 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
Microsoft (R) Incremental Linker Version 14.34.31937.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:foo.exe
/LIBPATH:C:\Users\rages\code\vcpkg\installed\x86-windows\lib
main.obj
torrent-rasterbar.lib
main.obj : error LNK2019: unresolved external symbol "public: __thiscall libtorrent::add_torrent_params::~add_torrent_params(void)" (??1add_torrent_params@libtorrent@@QAE@XZ) referenced in function _main
main.obj : error LNK2019: unresolved external symbol "struct libtorrent::add_torrent_params __cdecl libtorrent::parse_magnet_uri(class boost::basic_string_view<char,struct std::char_traits<char> >)" (?parse_magnet_uri@libtorrent@@YA?AUadd_torrent_params@1@V?$basic_string_view@DU?$char_traits@D@std@@@boost@@@Z) referenced in function _main
foo.exe : fatal error LNK1120: 2 unresolved externals

继续运行并寻找符号向我展示了这一点:dumpbin /exportstorrent-rasterbar.libadd_torrent_params

??1add_torrent_params@v2@libtorrent@@QAE@XZ (public: __thiscall libtorrent::v2::add_torrent_params::~add_torrent_params(void))

这与编译器所抱怨的有很大不同。我怀疑这是导致链接器失败的原因,但我不太确定我需要做些什么才能使其工作。如何让我的编译器和库在符号名称上达成一致?

C++ 未解析的外部 名称修改 libtorrent

评论

2赞 KungPhoo 2/8/2023
转储看起来你有一个 v2 库,但编译器似乎在寻找一个旧版本。也许您忘记了设置要使用的正确版本的一些 #define?您是否正在为库使用匹配的标头?
0赞 Oyvind Andersson 2/8/2023
库中的符号使用版本号“v2”进行修饰,而编译器所需的符号则不进行修饰。要解决此问题,您可以在包含 libtorrent 标头之前添加以下代码行: #define BOOST_ASIO_SEPARATE_COMPILATION 此行禁用 libtorrent 库中符号的版本修饰。如果尚未将 BOOST 库添加到链接器输入中,可能还需要这样做。
0赞 Sam Varshavchik 2/8/2023
编译器显示解离符号。工具(如 dumpbin)会显示损坏的符号。我现在觉得有点懒,其他人需要找到合适的骗子。
0赞 Ragesh 2/8/2023
@OyvindAndersson 感谢您的建议。这似乎为boost添加了更多未解析的外部符号(我可能可以通过将boost传递给链接器来解决),但原始的两个未解析符号仍然报告为错误。
0赞 Alan Birtles 2/8/2023
@SamVarshavchik实际上两者都以不同的顺序显示残缺和分离的符号,但符号实际上是不同的

答:

2赞 Ragesh 2/9/2023 #1

这是由于缺少定义所致。libtorrent 构建页面对此非常清楚:

在构建和链接 libtorrent 时,一个常见的错误是使用一组配置选项 (#defines) 进行构建,并使用一组不同的配置选项链接到它。由于 libtorrent 在头文件中有一些代码,因此如果它们看到不同的配置,则该代码将与构建的库不兼容。

始终确保在链接到 libtorrent 时定义与构建 libtorrent 时定义的 TORRENT_* 和 BOOST_* 宏相同。查看已定义宏的完整列表的最简单方法是使用 b2 命令行中添加的 -n -a 开关来构建 libtorrent,该开关输出所有编译器开关。

因此,我开始研究如何构建 libtorrent。我能够找到一些输出,其中显示了它为每个文件传递到的所有标志。果不其然,通过每一个标志,我的代码就可以编译了。vcpkg$VCPKG_DIR/buildtrees/libtorrent/install-x64-windows-rel-out.logcl

通过消除过程,我发现这是使它起作用的神奇酱汁。以下是编译它所需的最低限度:TORRENT_NO_DEPRECATE

> cl -DTORRENT_NO_DEPRECATE /nologo /EHsc /Fefoo.exe /IE:\vcpkg\installed\x64-windows\include main.cpp torrent-rasterbar.lib /link /LIBPATH:E:\vcpkg\installed\x64-windows\lib main.cpp

请注意,这只是为了说明符号不匹配的具体问题的解决方案。您可能应该使用日志中的完整定义集,以确保其他标头不会出现意外。vcpkg