1、dlopen是一个强大的库函数。该函数将打开一个动态库,并把它装入内存。该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的。比如 Apache Web 服务器利用这个函数在运行过程中加载模块,这为它提供了额外的能力。一个配置文件控制了加载模块的过程。这种机制使得在系统中添加或者删除一个模块时,都 不需要重新编译了。
可以在自己的程序中使用 dlopen()。dlopen() 在 dlfcn.h 中定义,并在 dl 库中实现。它需要两个参数:一个文件名和一个标志。
功能:打开一个动态链接库
包含头文件:
#include <dlfcn.h>
函数定义:
void * dlopen( const char * pathname, int mode );
函数描述:
在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。
mode:分为这两种
RTLD_LAZY 暂缓决定,等有需要时再解出符号
RTLD_NOW 立即决定,返回前解除所有未决定的符号。
RTLD_GLOBAL 允许导出符号
打开错误返回NULL
成功,返回被加载模块的句柄。
编译时候要加入 -ldl (指定dl库)
例如
gcc test.c -o test -ldl
当库被装入后,可以把 dlopen() 返回的句柄作为给 dlsym() 的第一个参数,以获得符号在库中的地址。使用这个地址,就可以获得库中特定函数的指针,并且调用装载库中的相应函数。
2、dlsym
函数原型
void* dlsym(void* handle,const char* symbol)
该函数在<dlfcn.h>文件中。
handle是由dlopen打开动态链接库后返回的句柄,symbol就是要求获取的函数的名称,函数返回值是void*,指向函数的地址,供调用使用
取动态对象地址:
#include <dlfcn.h>
void *dlsym(void *pHandle, char *symbol);
dlsym根据动态链接库操作句柄(pHandle)与符号(symbol),返回符号对应的地址。
使用这个函数不但可以获取函数地址,也可以获取变量地址。比如,假设在so中
定义了一个void mytest()函数,那在使用so时先声明一个函数指针:
void (*pMytest)(),然后使用dlsym函数将函数指针pMytest指向mytest函数,
pMytest = (void (*)())dlsym(pHandle, "mytest");
3、dlclose
函数原型:
int dlclose (void *handle);
函数描述:
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
4、dlerror
函数原型:
const char *dlerror(void);
函数描述:
当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。
接下来介绍一个实例来看看这几个函数的具体使用:
首先:将如下程序编译为动态链接库libcaculate.so,编译参数 gcc -fPIC -shared libcaculate.c -o libcaculate.so。程序如下:
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 div(int a,int b) { return (a/b); }
采用上面生成的libcaculate.so,写个测试程序如下,编译选型:gcc -rdynamic -o dl dl.c -ldl
#include<stdio.h> #include<stdlib.h> #include<dlfcn.h> //动态库路径 #define LIB_CACULATE_PATH "./libcaculate.so" typedef int (*Func)(int,int); int main() { void * handle; char * error;
//定义函数指针 Func func; //打开动态链接库 handle=dlopen(LIB_CACULATE_PATH,RTLD_LAZY); if(!handle){ fprintf(stderr,"%s ",dlerror()); exit(EXIT_FAILURE); } //清楚之前错误 dlerror(); //获取add函数 func=dlsym(handle,"add"); if((error = dlerror())!=NULL){ fprintf(stderr,"%s ",error); exit(EXIT_FAILURE); } printf("add: %d ",func(2,7)); func=dlsym(handle,"sub"); printf("sub: %d ",func(9,2)); func=dlsym(handle,"mul"); printf("mul: %d ",func(2,7)); func=dlsym(handle,"div"); printf("div: %d ",func(8,2)); dlclose(handle); return 0; }