|
0、生成动态链接库
- gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so
复制代码
1、动态链接库的隐式调用
将动态链接库和其他源程序文件或者目标文件一起链接,即为隐式调用(链接的目的是将函数的入口和函数体作一个匹配)
- # gcc main.c libdynamic.so -o main
复制代码此时main.a通常无法立即运行,因为系统找不到libdynamic.so的位置。 - $ ldd main
- linux-vdso.so.1 (0x00007fffaf12e000)
- libdynamic.so (can not find it)
- libc.so.6 => /lib64/libc.so.6 (0x00007f5905961000)
- /lib64/ld-linux-x86-64.so.2 (0x00007f5905b79000)
复制代码 在这里就要添加动态库的位置给系统,通过修改LD_LIBRARY_PATH,即在.bash_profile等位置添加一行: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/myname/mydynamiclib/ 保存并执行该配置 source .bash_profile。
此时再调用ldd main.a 即可看到每一项都有入口。
2、动态链接库的显式调用
显式调用动态链接库的过程,类似于使用malloc()和free()(c++中使用new和delete)管理动态内存空间,需要时就申请,不需要时就将资源释放。
显式调用,意思是在编写代码时,利用某些函数申请调用库函数,以及之后关闭与释放库函数资源。显示调用有助于减少内存占用,更经常用于一些占用内存的大项目中。
显示调用无需引入和动态链接库相关的头文件,但需要引入<dlfcn.h>头文件,因为需要该文件提供的一些函数。
1)要显式调用,必须先打开库文件,本质上即将库文件装载到内存中。语法为:
void *dlopen(const char *filename, int flag);
filename代表库文件位置和库名。如果仅仅提供库名,则该函数会从LD_LIBRARY_PATH位置寻找库文件。
flag参数的值有两种,RTLD_NOW 将库文件所有的资源都载入内存。RTLD_LAZY: 暂时不将库文件的资源载入内存,使用时才载入。
2)借助dlsym()函数可以获得指定函数在内存中的位置。语法为:
void *dlsym(void *handle, char *symbol);
handle表示已打开库文件的指针。
symbol代表指定目标函数的函数名。
如果dlsym()函数成功找到symbol指代的函数,则handle被赋予指向该函数的指针,否则handle为NULL。
3)dlclose()关闭已经打开的动态链接库。
int dlclose(void *handle)
handle表示已打开的库文件指针。
当函数返回0时,表示函数操作成功,反之,函数执行失败。
注意,调用dlclose()函数并不一定会将目标库彻底释放,而是使目标库引用计数减1,当引用计数为零时才触发释放。
4)dlerror()函数用于获取最近一次dlopen()、dlsym()和dlclose()这些函数操作失败的错误信息。语法:
const char *dlerror(void);
该函数不需要传递任何参数。同时,如果函数返回NULL,则表示最近一次操作执行成功。
使用显式调用的例程:
- #include <stdio.h>
- #include <dlfcn.h>
- int main()
- {
- int m,n;
- //打开库文件
- void* handler = dlopen("libmymath.so",RTLD_LAZY);
- if(dlerror() != NULL){
- printf("%s",dlerror());
- }
-
- //获取库文件中的 add() 函数
- int(*add)(int,int)=dlsym(handler,"add");
- if(dlerror()!=NULL){
- printf("%s",dlerror());
- }
-
- //获取库文件中的 sub() 函数
- int(*sub)(int,int)=dlsym(handler,"sub");
- if(dlerror()!=NULL){
- printf("%s",dlerror());
- }
-
- //获取库文件中的 div() 函数
- int(*div)(int,int)=dlsym(handler,"div");
- if(dlerror()!=NULL){
- printf("%s",dlerror());
- }
- //使用库文件中的函数实现相关功能
- printf("Input two numbers: ");
- scanf("%d %d", &m, &n);
- printf("%d+%d=%d\n", m, n, add(m, n));
- printf("%d-%d=%d\n", m, n, sub(m, n));
- printf("%d÷%d=%d\n", m, n, div(m, n));
- //关闭库文件
- dlclose(handler);
- return 0;
复制代码 编译的指令:
- $ gcc main.c -ldl -o main
复制代码 其中-ldl 是gcc调用<dlfcn.h>时指明这个头文件(库文件)的命令。
|
-
|