Linux下动态库的层次结构及静态链接与动态链接的区别如下图:
图 1. Linux 中的库层次结构
图 2. 静态链接与动态链接
下面以一个简单的动态库为例讲解动态链接与动态加载方法:
动态库示例:
add.c
int add(int a,intb){
return (a+b);
}
编译动态库:gcc -shared -o libadd.so add.c 生成 libadd.so
动态链接方法:在编译程序时,指定要链接的库文件即可,此时调用共享库只需要其头文件即可。
示例:
test.c
#include<stdio.h>
#include <dlfcn.h>
int add(int,int);
int main(int argc, char *argv[])
{
sum=add(10,11);
printf("sum=%d",sum);
}
编译程序:gcc -ladd -o test test.c
-l 参数表示要链接的动态链接库,若路径不在标准库文件路径下可用-L 包含。
动态加载方法:通过下列API完成
表 1. Dl API
函数 | 描述 |
dlopen | 使对象文件可被程序访问 |
dlsym | 获取执行了 dlopen 函数的对象文件中的符号的地址 |
dlerror | 返回上一次出现错误的字符串错误 |
dlclose | 关闭目标文件 |
示例:
test.c
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char *argv[])
{
void *dl_handler=NULL;
int (*func)(int,int);
char *error;
int sum;
dl_handler = dlopen("add.so",RTLD_LAZY);
if(!dl_handler)
{
printf("open:%s\n",dlerror());
return 0;
}
func=dlsym(dl_handler,"add");
error =dlerror();
if(error!=NULL)
{
printf("find:%s\n",error);
return 0;
}
sum=(*func)(10,11);
printf("sum=%d",sum);
dlclose(dl_handler);
}
编译程序:gcc -otest test.c -ldl
-ldl 表明将 dllib 链接于该程序,即可调用DL的API
共享库的路径:可以放在系统共享库目录:/usr/lib下,也可以通过环境变量LD_LIBRARY_PATH设置