Linux下采用dlopen调用动态库的方法

一、前言

  为了使程序方便扩展,具备通用性,可以采用插件形式。采用异步事件驱动模型,保证主程序逻辑不变,将各个业务已动态链接库的形式加载进来,这就是所谓的插件。linux提供了加载和处理动态链接库的系统调用,非常方便。

    生成动态链接库语法: 

  •  
gcc -fPIC -shared <源文件> -o libxxx.so

    用法示例:  

  •  
gcc -fPIC -shared sum.c -o libsum.so

二、dlopen系列函数

    Linux提供以下4个函数用于处理动态库:

 

 

#include <dlfcn.h>void *dlopen(const char *filename, int flag);char *dlerror(void);void *dlsym(void *handle, const char *symbol);int dlclose(void *handle);

    Link with -ldl.   

    注意:   编译时候要加入 -ldl (指定dl库)

2.1 dlopen函数介绍

功能:打开一个动态链接库

包含头文件: #include<dlfcn.h>

函数定义: 

  •  
void *dlopen( const char * pathname, int flag);

函数描述: 使用dlopen函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。完毕之后,使用dlclose()来卸载打开的库。

flag:分为这2种

RTLD_LAZY 暂缓决定,等有需要时再解出符号

RTLD_NOW 立即决定,返回前解除所有未决定的符号。

返回值:

打开错误返回NULL

成功,返回库引用

使用dlopen:

    dlopen()是一个强大的库函数。该函数将打开一个新库,并把它装入内存。该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的。当库被装入后,可以把 dlopen() 返回的句柄作为给 dlsym() 的第一个参数,以获得符号在库中的地址。使用这个地址,就可以获得库中特定函数的指针,并且调用装载库中的相应函数。

    示例代码:

 

 

#include <stdio.h>#include <dlfcn.h>int main(){    int (*p)(int,int); //函数指针    void *handle;    /*1. 打开库文件*/    handle=dlopen("./sum/libsum.so",RTLD_LAZY);    if(handle==NULL)    {        printf("库打开失败!\n");        return 0;    }    /*2. 获取指定的函数地址*/    p=dlsym(handle,"sum");    if(p==NULL)    {        printf("函数地址获取失败!\n");        return 0;    }    //调用函数    printf("sum=%d\n",p(12,12));    /*3. 关闭库文件*/    dlclose(handle);    return 0;}

2.2 dlsym()函数介绍

    dlsym()的函数原型是:

  •  
void* dlsym(void* handle,const char* symbol)

    该函数在<dlfcn.h>文件中。

    handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数的名称,函数返回值是void*,指向函数的地址,供调用使用

dlsym根据动态链接库操作句柄(pHandle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。

     比如:假设在so中定义了一个

voidmytest()函数,那在使用so时先声明一个函数指针:void(*pMytest)(), 然后使用dlsym函数将函数指针pMytest指向mytest函数,pMytest = (void(*)())dlsym(pHandle, "mytest");

2.3 dlclose函数介绍

包含头文件: #include<dlfcn.h>

函数原型为:  int dlclose (void *handle);

函数描述: dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

2.4 dlerror函数介绍

包含头文件: #include<dlfcn.h>

函数原型: constchar *dlerror(void);

函数描述:当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。