赞
踩
函数名 | 功能描述 |
---|---|
dlopen | 打开对象文件,使其可被程序访问 |
dlsym | 获取执行了 dlopen 函数的对象文件中的函数的地址 |
dlerror | 该函数没有参数,它会在发生前面的错误时返回一个字符串,同时将其从内存中清空; 在没有错误发生时返回 NULL, |
dlclose | 关闭目标文件。如果无需再调用共享对象的话,应用程序可以调用该方法来通知操作系统不再需要句柄和对象引用了。它完全是按引用来计数的,所以同一个共享对象的多个用户相互间不会发生冲突(只要还有一个用户在使用它,它就会待在内存中)。任何通过已关闭的对象的 |
新建一个sort.c文件,写排序函数
使用gcc -o libsort.so -fPIC -shared sort.c
产生libsort.so库。
fPIC
:(Position Independent Code)地址无关代码,fPIC的作用
Linux位置无关代码实现,浅谈位置无关代码_weixin_39521520的博客-CSDN博客
- void InsertSort(int* a,int len)
- {
- int begin = 1;
- int i = 0;
- while(begin < len)
- {
- int key = a[begin];
- for(i = begin-1;i>=0;i--)
- {
- if(a[i]<=key)
- {
- a[i+1] = key;
- break;
- }
- a[i+1] = a[i];
- }
- if(i<0)
- a[0] = key;
- begin++;
- }
-
- }

1.编译过程中连接到可执行程序,
2.用dlopen()动态加载
新建main.c文件:
使用命令gcc -o main main.c -lsort -L.
编译。
export LD_LIBRARY_PATH=$(pwd),
即.so库的路径添加到环境变量中,因为程序运行时会先加载所依赖的so库到内存中,so加载成功后才真正启动程序。- #include <stdio.h>
- int main()
- {
- int i = 0;
- int test[]={1,3,5,7,2,4,6,8};
- InsertSort(test,8);
- for(i=0;i<8;i++)
- {
- printf("%d,",test[i]);
- }
- printf("\n");
- return 0;
- }
新建main2.c文件:
使用命令gcc -o main2 main2.c -ldl
编译。动态加载.so库的话需要-ldl。
运行./main2后输出递增序列,调用成功。
- #include <stdlib.h>
- #include <stdio.h>
- #include <dlfcn.h>
- int main()
- {
- int i = 0;
- int test[]={1,3,5,7,2,4,6,8};
- int (*sort)(int*,int);
- void *handle = dlopen("./libsort.so",RTLD_LAZY);
- if(!handle)
- {
- printf("dlopen error :%s\n",dlerror());
- return -1;
- }
- sort = dlsym(handle,"InsertSort");
- if(!sort)
- {
- printf("dlsym error :%s\n",dlerror());
- }
- sort(test,8);
- dlclose(handle);
- for(i=0;i<8;i++)
- printf("%d,",test[i]);
- printf("\n");
- return 0;
- }

- readelf -s private.so
- nm -D private.so
readelf nm objdump 命令详解_耿小渣的博客-CSDN博客_nm objdump
nm和readelf命令的区别 - foo__hack - 博客园
向客户提供动态链接库(.so)时,有些关键的函数名不希望暴露出去,此时便可以通过gcc的-fvisibility=hidden选项对编译生成的so进行函数符号隐藏,如:LOCAL_CPPFLAGS +=-fvisibility=hidden,执行编译后,使用nm -D xxx.so命令或者readelf --symbols xxx.so查看函数名的确被隐藏,但此时是将所有函数名都隐藏了,那么客户加载so时需要调用的接口函数名(xxx)也会找不到定义,导致编译报undefined reference to xxx错误,所以需要暴露(导出)的函数前应该增加属性__attribute__ ((visibility("default")))设置成可见
例如,全局函数int structure_func(int i, struct test s, double d),其经过符号改编后,函数名变成了_Z14structure_funci4testd。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。