意见箱
恒创运营部门将仔细参阅您的意见和建议,必要时将通过预留邮箱与您保持联络。感谢您的支持!
意见/建议
提交建议

dlopen调用动态库运行出现undefined symbol

来源:恒创科技 编辑:恒创科技编辑部
2024-01-28 11:22:59


1. 库源码

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int add(int a,int b)
{
return (a + b);
}

int sub(int a, int b)
{
return (a - b);
}

int mul(int a, int b)
{
return (a * b);
}

int div1(int a, int b)
{
return (a / b);
}

2. 将库源码命名为DyncAppLib.cpp,用g++编译


dlopen调用动态库运行出现undefined symbol

g++ -fPIC -shared DyncAppLib.cpp  -o libDync.so   

通过nm工具看动态库函数列表

root@0ca8a8fd81e8:/data/# nm -D libDync.so 
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
00000000000006f0 T _Z3addii
0000000000000716 T _Z3mulii
0000000000000704 T _Z3subii
0000000000000729 T _Z4div1ii
0000000000200aa8 B __bss_start
w __cxa_finalize
w __gmon_start__
0000000000200aa8 D _edata
0000000000200ab0 B _end
000000000000073c T _fini
00000000000005a0 T _init

3. 将库源码命名为DyncAppLib.c,用gcc编译

gcc -fPIC -shared DyncAppLib.c  -o libDync.so   
root@0ca8a8fd81e8:/data# nm -D libDync.so 
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
0000000000200a48 B __bss_start
w __cxa_finalize
w __gmon_start__
0000000000200a48 D _edata
0000000000200a50 B _end
000000000000070c T _fini
0000000000000568 T _init
00000000000006c0 T add
00000000000006f9 T div1
00000000000006e6 T mul
00000000000006d4 T sub

4. 主函数命名为DyncAppTest.c源码

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

//动态链接库路径
#define LIB_CACULATE_PATH "./libDync.so"

//函数指针
typedef int (*CAC_FUNC)(int, int);

int main()
{
void *handle;
char *error;
CAC_FUNC cac_func = NULL;

//打开动态链接库
handle = dlopen(LIB_CACULATE_PATH, RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}

//清除之前存在的错误
dlerror();

//获取一个函数
*(void **) (&cac_func) = dlsym(handle, "add");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
printf("add: %d\n", (*cac_func)(2,7));

cac_func = (CAC_FUNC)dlsym(handle, "sub");
printf("sub: %d\n", cac_func(9,2));

cac_func = (CAC_FUNC)dlsym(handle, "mul");
printf("mul: %d\n", cac_func(3,2));

cac_func = (CAC_FUNC)dlsym(handle, "div1");
printf("div: %d\n", cac_func(8,2));

//关闭动态链接库
dlclose(handle);
exit(EXIT_SUCCESS);
}

5. 主函数g++编译、运行

root@0ca8a8fd81e8:/data# g++ -rdynamic -o DyncApp DyncAppTest.cpp -ldl
root@0ca8a8fd81e8:/data# ./DyncApp
./libDync.so: undefined symbol: add

6. 主函数gcc编译、运行

root@0ca8a8fd81e8:/data# gcc -o DyncAppTest DyncAppTest.c -ldl   
root@0ca8a8fd81e8:/data# ./DyncAppTest

7. 从上面分析,c++编译成动态库后其接口无法被访问,需要修改,这里用到extern "C",修改后的库源码DyncAppLib.cpp为

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

extern "C"{
int add(int a,int b)
{
return (a + b);
}

int sub(int a, int b)
{
return (a - b);
}

int mul(int a, int b)
{
return (a * b);
}

int div1(int a, int b)
{
return (a / b);
}
}
root@0ca8a8fd81e8:/data# g++ -fPIC -shared DyncAppLib.cpp  -o libDync.so 
root@0ca8a8fd81e8:/data# ./DyncAppTest
add: 9
sub: 7
mul: 6
div: 4

上一篇: S3C2440 I2C总线控制 下一篇: 手机怎么远程登录云服务器?