您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 规章制度 > dlopendlsym和dlclose的使用和举例
dlopen、dlsym和dlclose的使用和举例之前用过这三个函数一直没时间整理一下。今天抽时间整理一下。1、函数简介dlopen基本定义功能:打开一个动态链接库包含头文件:#includedlfcn.h函数定义:void*dlopen(constchar*pathname,intmode);函数描述:在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。mode:分为这两种RTLD_LAZY暂缓决定,等有需要时再解出符号RTLD_NOW立即决定,返回前解除所有未决定的符号。RTLD_LOCALRTLD_GLOBAL允许导出符号RTLD_GROUPRTLD_WORLD返回值:打开错误返回NULL成功,返回库引用编译时候要加入-ldl(指定dl库)dlsym()功能:根据动态链接库操作句柄与符号,返回符号对应的地址。包含头文件:#includedlfcn.h函数定义:void*dlsym(void*handle,constchar*symbol)函数描述:dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数或全局变量的名称。dlclose()dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。上述都是摘抄,总结为链接的时候需要用到dl库,编译的时候需要加上dlfcn.h头文件。才能保证编译不会报错。2、生成动态库hello.c函数原型:#includesys/types.h#includesignal.h#includestdio.h#includeunistd.htypedefstruct{constchar*module;int(*GetValue)(char*pszVal);int(*PrintfHello)();}hello_ST_API;intGetValue(char*pszVal){intretval=-1;if(pszVal)retval=sprintf(pszVal,%s,123456);printf(%s,%d,pszVer=%s\n,__FUNCTION__,__LINE__,pszVal);returnretval;}intPrintfHello(){intretval=-1;printf(%s,%d,helloeveryone\n,__FUNCTION__,__LINE__);return0;}consthello_ST_APIHello={.module=hello,GetValue,PrintfHello,};编译的时候用指令:gcc-shared-ohello.sohello.c上面的函数是用一个全局结构体hello来指向。在dlsym定义中说不仅可以获取函数的地址,还可以获取全局变量的地址。所以此处是想通过dlsym来获取全局变量的地址。好处自己慢慢体会。3、dlopen代码#includesys/types.h#includesignal.h#includestdio.h#includeunistd.h#includedlfcn.htypedefstruct{constchar*module;int(*GetValue)(char*pszVal);int(*PrintfHello)();}hello_ST_API;intmain(intargc,char**argv){hello_ST_API*hello;inti=0;void*handle;charpsValue[20]={0};handle=dlopen(“库存放的绝对路径,你可以试试相对路径是不行的,RTLD_LAZY);if(!handle){printf(%s,%d,NULL==handle\n,__FUNCTION__,__LINE__);return-1;}dlerror();hello=dlsym(handle,Hello);if(!hello){printf(%s,%d,NULL==handle\n,__FUNCTION__,__LINE__);return-1;}if(hello&&hello-PrintfHello)i=hello-PrintfHello();printf(%s,%d,i=%d\n,__FUNCTION__,__LINE__,i);if(hello&&hello-GetValue)i=hello-GetValue(psValue);if(hello&&hello-module){printf(%s,%d,module=%s\n,__FUNCTION__,__LINE__,hello-module);}dlclose(handle);return0;}编译指令:gcc-otesthello_dlopen.c-ldl运行./test结果如下。PrintfHello,27,helloeveryonemain,36,i=0GetValue,19,pszVer=123456main,42,module=hello可以看到结果正常出来了。看到没用?dlsym找到全局结构体hello后,可以直接用这个全局结构体指针来使用库里面的函数了,因为我们有时候提供的库不仅仅是一个两个函数的,一般的一个库都会存在多个函数,用这种方式就可以直接使用了。不然找函数名称的话要写多少个dlsym啊?dlopen,dlsym打开动态库,并装入内存除了传统的包含头文件.h文件可以调用函数外,还有很好的办法便是这个,加载动态库函数句柄,如函数名为fun(inta,charb),则加载为fun.功能:打开一个动态链接库包含头文件:#includedlfcn.h函数定义:void*dlopen(constchar*pathname,intmode);dlopen()是一个强大的库函数。该函数将打开一个新库,并把它装入内存。该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的。比如ApacheWeb服务器利用这个函数在运行过程中加载模块,这为它提供了额外的能力。一个配置文件控制了加载模块的过程。这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了。可以在自己的程序中使用dlopen()。dlopen()在dlfcn.h中定义,并在dl库中实现。它需要两个参数:一个文件名和一个标志。文件名可以是我们学习过的库中的soname。标志指明是否立刻计算库的依赖性。如果设置为RTLD_NOW的话,则立刻计算;如果设置的是RTLD_LAZY,则在需要的时候才计算。另外,可以指定RTLD_GLOBAL,它使得那些在以后才加载的库可以获得其中的符号。当库被装入后,可以把dlopen()返回的句柄作为给dlsym()的第一个参数,以获得符号在库中的地址。使用这个地址,就可以获得库中特定函数的指针,并且调用装载库中的相应函数。dlsym()的函数原型是void*dlsym(void*handle,constchar*symbol)该函数在dlfcn.h文件中。handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数的名称,函数返回值是void*,指向函数的地址,供调用使用例程#includestdio.h#includestdlib.h#includedlfcn.hintmain(intargc,char**argv){void*handle;double(*cosine)(double);char*error;handle=dlopen(libm.so,RTLD_LAZY);if(!handle){fprintf(stderr,%s\n,dlerror());exit(EXIT_FAILURE);}dlerror();*(void**)(&cosine)=dlsym(handle,cos);if((error=dlerror())!=NULL){fprintf(stderr,%s\n,error);exit(EXIT_FAILURE);}printf(%f\n,(*cosine)(2.0));dlclose(handle);exit(EXIT_SUCCESS);}
本文标题:dlopendlsym和dlclose的使用和举例
链接地址:https://www.777doc.com/doc-2910028 .html