动态加载库时出现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
任何帮助都将不胜感激。
答案 0 :(得分:9)
你很可能会在这里看到名字管理。
如果要将dlopen()
/ dlsym()
与C ++共享库一起使用,则需要:
dlsym()
查找的函数声明为extern "C" { ... }
,以便C ++编译器为它们创建 unmangled 名称。extern "C" { ... }
这样做,并且可以创建一个未编码的名称,它将在ELF符号表中逐字结束。然后,您可以使用dlsym()
查找它,就像使用任何C函数一样。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
这些是 mangled 名称,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
这意味着对于这个lib,如果你想从它获取std::unexpected()
的函数指针,你必须请求dlsym(hdl, "_ZN10__cxxabiv112__unexpectedEPFvvE");
使查找成功。