| 
 | 
 
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>时指明这个头文件(库文件)的命令。 
 
 
 
 
 
 
 
 |   
- 
 
 
 
 
 
 
 
 |