使用"DLopen"时有关"undefined symbol"的共享库错误



首先,这里是我的最小可复制程序:

CMakeLists.txt:

cmake_minimum_required(VERSION 3.17)
project(untitled4)
set(CMAKE_CXX_STANDARD 17)
add_library(lib1 SHARED lib1.cpp)
add_executable(untitled4 main.cpp)
target_link_libraries(untitled4 PRIVATE dl)

main.cpp:

#include "iostream"
#include <dlfcn.h>
int Test() {
return 123456;
}
int main() {
auto* handler = dlopen("/home/liu/source/untitled4/cmake-build-debug/liblib1.so", RTLD_LAZY|RTLD_GLOBAL);
if (!handler) {
std::cerr << dlerror();
exit(1);
}
}

和lib1.cpp:

#include "iostream"
extern int Test();
class Foo {
public:
Foo() {
std::cout << Test() << std::endl;
}
};
Foo foo;

现在让我来解释一下:

正如你所看到的,我在main.cpp中定义了一个名为Test的函数,我希望共享库liblib1.so在加载时调用它。

但当我运行main()函数时,有一个错误日志说:

/home/liu/source/untitled4/cmake-build-debug/liblib1.so: undefined symbol: _Z4Testv

我使用nm untitled4 |grep Test检查符号,符号似乎存在:

0000000000000b87 t _GLOBAL__sub_I__Z4Testv
0000000000000aea T _Z4Testv

那么我做错了什么?如何解决此问题?

需要注意的一点是,在实际情况下,lib1的构建和main.cpp的构建是完全分离的,两个构建互不了解。但是,如果这可以解决问题(如果没有其他方法的话(,我可以把它们变成一个构建(非常困难(。

附言:我试着用extern";C";在两个文件中封装Test(),但不起作用,这似乎不是C/C++函数命名的问题。

添加了链接器选项-rdynamic后,您的代码不会失败未定义符号";。

您可以使用set_target_properties(untitled4 PROPERTIES ENABLE_EXPORTS 1)target_link_options(untitled4 BEFORE PRIVATE "-rdynamic")进行设置。

示例:

cmake_minimum_required(VERSION 3.17)
project(untitled4)
set(CMAKE_CXX_STANDARD 17)
add_library(lib1 SHARED lib1.cpp)
add_executable(untitled4 main.cpp)
set_target_properties(untitled4 PROPERTIES ENABLE_EXPORTS 1)
target_link_libraries(untitled4 PRIVATE dl)

最新更新