先从百度百科把dlsym的简介拉过来:
功能:根据动态链接库操作句柄与符号,返回符号对应的地址;
函数定义:void*dlsym(void*handle,constchar*symbol);
函数描述:dlsym(dynamic library symbol) 根据 动态链接库 操作句柄(handle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。 handle:由dlopen打开动态链接库后返回的指针; symbol:要求获取的函数或全局变量的名称。 返回值: void* 指向函数的地址,供调用使用。
现在来看三个示例,main.c、test_C.c、test_C++.cpp:
/************** main.c gcc main.c -ldl -o main **************/ #include <stdio.h> #include <dlfcn.h> void main() { void *handle; void(*test)(); handle = dlopen("/home/auo/Study/C/name mangling/libtest_C.so", RTLD_NOW); if(!handle) return -1; test = (void(*)())dlsym(handle, "test"); printf("test in C addr:\t%x\n", test); test(); handle = dlopen("/home/auo/Study/C/name mangling/libtest_C++.so", RTLD_NOW); if(!handle) return -1; test = (void(*)())dlsym(handle, "test"); printf("test in C++ addr:\t%x\n", test); test(); }
/************** test_C.c gcc test_C.c -fPIC -shared -o libtest_C.so **************/ #include <stdio.h> void test() { printf("Call test in C\n"); }
/************** test_C++.cpp g++ test_C++.cpp -fPIC -shared -o libtest_C++.so **************/ #include <stdio.h> void test() { printf("Call test in C++\n"); }
编译完成后得到可执行程序main,动态库文件libtest_C.so、libtest_C++.sp。在终端执行main函数结果如下:
dlsym函数并没有成功找到由g++编译后的libtest_C++.so里的函数test的地址,我们知道dlsym函数是通过查找指定动态库中的符号表来获得符号地址的,我们现在用readelf查看下libtest_C++.so的符号表:
清楚的看到并没有符号test的信息,而只有_Z4testv的符号信息,所以当dlsym查找符号test的时候自然就返回0了。我们再看一下libtest_C.so的符号表:
可以看到libtest_C.so符号表是存在test符号的。
那么,为什么g++编译器会将符号test更名为_Z4testv呢,这个就是因为name mangling机制。具体来讲就是因为C++存在函数重载,C++编译器在编译的时候会根据一个函数的名字、参数、返回值来生产一个独一无二的符号名字,这样才Link的时候,才能区分出不同的函数。extern “C” void test()可以避免name mangling(事实上,就是告诉编译器这个函数按照C的规则进行编译,自然就不会发生name mangling)。
转载于:https://my.oschina.net/auo/blog/315871
今天的文章dlsym与C++分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/5039.html