问题描述
动态加载库时,我收到未定义的符号
错误。
这是我的代码片段产生这个错误:
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\\\
,dlerror());
exit(1);
}
create =(MyClass *(*)())dlsym(lib_handle,create_object);
if((error = dlerror())!= NULL)
{
fprintf(stderr,%s\\\
,error);
exit(1);
}
destroy =(void(*)(MyClass *))dlsym(lib_handle,destroy_object);
MyClass * myClass =(MyClass *)create;
destroy(myClass);
dlclose(lib_handle);
}
但是,当我简单地通过注释上面的代码和导出库路径一切正常装载库like charm。
对于动态链接,我在命令提示符下使用以下命令。
g ++ -Wl, - export-dynamic shared_user.cpp -ldl
任何帮助将不胜感激。
你很可能看到的名称重整的这里的行动。
如果您想使用C ++共享库使用 dlopen()
/ dlsym()
- 通过
dlsym()
声明要查找的函数C $ C>的externC{...} 从而使C ++编译器创建的重整的的为他们的名字。结果
这是如果只可能您尝试访问的函数是非成员或静态成员函数,并且不重载(只有单个签名);如果一个请求的编译器这样做通过的externCC ++不能创建在其他情况下重整的名字。结果
和可以创建一个未解析的名称,它在ELF符号表中逐字地结束。那么你可以看看它使用
{...}则dlsym()
就像你会为所有的C函数。 - 找到了什么的 的名称。
后者可以通过
nm
实用程序来完成。例如:$ nm libstdc ++。 grep -v'^'| grep的意外
0000000000000000牛逼__cxa_call_unexpected
0000000000000000牛逼_ZN10__cxxabiv112__unexpectedEPFvvE
0000000000000000牛逼_ZSt10unexpectedv
0000000000000000牛逼_ZSt14set_unexpectedPFvvE
0000000000000000ð_ZN10__cxxabiv120__unexpected_handlerE
这些是错误的名称,C ++编译器实际放入ELF对象。如果您使用
-C
选项请求nm
到解构您将获得:$ nm -C libstdc ++。 grep -v'^'|用grep意想不到的
0000000000000000牛逼__cxa_call_unexpected
0000000000000000牛逼__cxxabiv1 :: __意外(无效(*)())
0000000000000000牛逼的std ::意想不到的()
0000000000000000牛逼的std :: set_unexpected( void(*)())
0000000000000000 D __cxxabiv1 :: __ unexpected_handler
lib中,如果你想为函数指针
的std ::意想不到的()
从中,你有权要求则dlsym(HDL ,_ZN10__cxxabiv112__unexpectedEPFvvE);
以使查找成功。I am getting
undefined symbol
error while loading library dynamically.Here is my code snippet that generates this error :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); }
But when I load library simply by commenting above code and exporting library path everything works like charm.
For dynamic linking I am using the following command on command prompt.
g++ -Wl,--export-dynamic shared_user.cpp -ldl
Any help would be appreciated.
解决方案You're very likely seeing Name Mangling in action here.
If you want to use
dlopen()
/dlsym()
with C++ shared libraries, you either need to:- declare the functions you want to lookup through
dlsym()
asextern "C" { ... }
so that the C++ compiler creates unmangled names for them.
This is only possible if the function you try to access is a non-member or static member function, and not overloaded (only a single signature); C++ can't create unmangled names in other situations.
If one requested the compiler to do so viaextern "C" { ... }
and it's possible to create an unmangled name, it ends up verbatim in the ELF symbol table. You can then look it up usingdlsym()
exactly like you would for any C function. - Find out what the mangled name of the function is, and use that in your
dlsym()
call.
The latter you can do via the
nm
utility. For example:$ 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
These are the mangled names, what the C++ compiler has actually put into the ELF object. If you use the
-C
option to requestnm
to demangle the names for you, you get:$ 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
That means for this lib, if you'd want to get the function pointer to
std::unexpected()
from it, you'd have to requestdlsym(hdl, "_ZN10__cxxabiv112__unexpectedEPFvvE");
to make the lookup succeed.这篇关于在动态加载共享库时获取未定义的符号错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
- declare the functions you want to lookup through