c++ - 共享对象中的符号名称与 .cpp 文件中的函数不同

标签 c++ cmake shared-objects

在项目环境中,我想将共享对象的源文件从 c 更改为 cpp。我也确保更改了 CMakeLists.txt 中的条目:

add_library(*name* SHARED *mysource*.cpp)
target_link_libraries(*name as target* *item*)

构建过程运行良好。不幸的是,当我尝试使用它时,出现错误,无法找到 .so 中的函数。

使用 objdump -T 检查共享对象内的动态符号表后,我发现符号名称与源文件中的符号名称不同。 例如

int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx);

变成

_Z17sr_plugin_init_cbP16sr_session_ctx_sPPv

在我的 Visual Studio 代码中,它表示它可以正确构建对象并链接共享库,并且它在输出中也从 C 更改为 CXX,并且即使某些代码仅是 C++,也不会给我任何错误。

为什么符号名称会改变?

最佳答案

Why do the symbol names change?

C++ 有一个称为函数重载的功能。基本上发生的情况是您声明两个名称相同但略有不同的函数:

int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx);
int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx, int some_arg);

或者更糟糕的情况:

struct A {
    # each of these functions can be different depending on the object
    void func();
    void func() const;
    void func() volatile;
    void func() volatile const;
};

函数的名称相同。链接器看不到 C++ 源代码,但它仍然必须区分两个函数才能与之链接。因此,C++ 编译器“破坏”了函数名称,以便链接器可以区分它们。为了简单起见,它可能看起来像:

sr_plugin_init_cb_that_doesnt_take_int_arg
sr_plugin_init_cb_that_takes_int_arg
A_func
A_func_but_object_is_const
A_func_but_object_is_volatile
A_func_but_object_is_volatile_and_const

名称修改的规则很复杂,目的是使名称尽可能短。它们必须考虑任意数量的模板、参数、对象、名称、限定符、lambda、重载、运算符等,并生成唯一的名称,并且它们必须仅使用与特定体系结构上的链接器兼容的字符。例如here是 gnu g++ 编译器使用的名称修改的引用。

符号名称_Z17sr_plugin_init_cbP16sr_session_ctx_sPPv是由函数的编译器名称损坏的。

关于c++ - 共享对象中的符号名称与 .cpp 文件中的函数不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57812482/

相关文章:

c++ - 在 QT Creator 项目中使用动态库

c++ - Cmake 错误 : set command does not like the same . h files from a previous set command

java - 链接共享对象时出现问题

c++ - QAxObject Excel 工作表 -- 为整个 Excel 工作表设置默认字体

c++ - C++ 中的跨平台多线程?

c++ - Visual Studio - Cmake 项目 - 添加 NetCDF

java - 线程 "main"java.lang.UnsatisfiedLinkError : undefined symbol: Test 中的异常

android-ndk - 如何在另一个Android应用程序中使用预编译的.so文件?

c++ - 为什么 assembly 对我来说似乎不一致?

c++ - C 条件运算符的令人困惑的结果