动态加载库时出现undefined symbol
错误。
这是我生成此错误的代码片段:
int main ()
{
void *lib_handle = NULL;
MyClass* (*create)();
void (*destroy)(MyClass*);
char *error;
lib_handle = dlopen ("./libshared.so", RTLD_LAZY);
if (lib_handle == NULL)
{
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
create = (MyClass* (*)()) dlsym(lib_handle, "create_object");
if ((error = dlerror()) != NULL)
{
fprintf(stderr, "%s\n", error);
exit(1);
}
destroy = (void (*)(MyClass*)) dlsym(lib_handle, "destroy_object");
MyClass *myClass = (MyClass*) create;
destroy(myClass);
dlclose(lib_handle);
}
但是当我简单地通过评论上面的代码和导出库路径来加载库时,一切都像魅力一样。
对于动态链接,我在命令提示符下使用以下命令。
g++ -Wl,--export-dynamic shared_user.cpp -ldl
如有任何帮助,我们将不胜感激。
最佳答案
您很可能会在这里看到Name Mangling。
如果您想将 dlopen()
/dlsym()
与 C++ 共享库一起使用,您需要:
- 将您要通过
dlsym()
查找的函数声明为extern "C"{ ... }
以便 C++ 编译器创建unmangled 他们的名字。
这仅在您尝试访问的函数是非成员函数或静态成员函数且未重载(仅单个签名)时才有可能; C++ 无法在其他情况下创建未损坏的名称。
如果有人通过extern "C"{ ... }
请求编译器这样做,并且有可能创建一个未损坏的名称,它最终会逐字地出现在 ELF 符号表中。然后,您可以像查找任何 C 函数一样使用dlsym()
查找它。 - 找出函数的损坏名称是什么,并在您的
dlsym()
调用中使用它。
后者可以通过 nm
实用程序完成。例如:
$ nm libstdc++.a | grep -v '^ ' | grep unexpected
0000000000000000 T __cxa_call_unexpected
0000000000000000 T _ZN10__cxxabiv112__unexpectedEPFvvE
0000000000000000 T _ZSt10unexpectedv
0000000000000000 T _ZSt14set_unexpectedPFvvE
0000000000000000 D _ZN10__cxxabiv120__unexpected_handlerE
这些是错位 名称,C++ 编译器实际上已放入 ELF 对象中。如果您使用 -C
选项请求 nm
为您demangle 名称,您将获得:
$ nm -C libstdc++.a | grep -v '^ ' | grep unexpected
0000000000000000 T __cxa_call_unexpected
0000000000000000 T __cxxabiv1::__unexpected(void (*)())
0000000000000000 T std::unexpected()
0000000000000000 T std::set_unexpected(void (*)())
0000000000000000 D __cxxabiv1::__unexpected_handler
这意味着对于这个库,如果你想从中获取指向 std::unexpected()
的函数指针,你必须请求 dlsym(hdl, "_ZN10__cxxabiv112__unexpectedEPFvvE");
使查找成功。
关于c++ - 动态加载共享库时出现 undefined symbol 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9837009/