Linux 7 共享库so的动态加载dlopen

前面的共享库是通过静态加载的方式使用的,即将共享库编译进代码中,每次共享库修改了都必须重新编译使用该库的源文件。
这里使用动态加载的方法使用动态链接库,只要动态链接库里面相应的函数没有改变,使用动态加载的源文件不需要重新编译,即可使用。可以减小程序的大小,还能方便的扩展动态库。如果不是很常用,程序启动的时候可以不加载,需要用的时候才加载。

使用方式:
dlopen打开动态链接库
dlsym使用库中的函数
dlclose关闭打开的动态链接库

dlopen
基本定义
功能:打开一个动态链接库
包含头文件: #include <dlfcn.h> 
函数定义: void * dlopen( const char * pathname, int mode ); 
函数描述: 在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。 
mode:分为这两种 
RTLD_LAZY 暂缓决定,等有需要时再解出符号。
RTLD_NOW 立即决定,返回前解除所有未决定的符号。 
RTLD_LOCAL RTLD_GLOBAL 允许导出符号。
RTLD_GROUP RTLD_WORLD 返回值: 打开错误返回NULL,成功返回库引用。
编译时候要加入 -ldl (指定dl库) 
例如 gcc test.c -o test -ldl

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),返回符号对应的地址。
使用这个函数不但可以获取函数地址,也可以获取变量地址。

dlclose() 
包含头文件: #include <dlfcn.h> 
函数原型为: int dlclose (void *handle); 
函数描述: dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

dlerror() 
包含头文件: #include <dlfcn.h> 
函数原型: const char *dlerror(void); 
函数描述: 当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

动态库:

/* calculate.c */

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);
}

动态加载:

/* test.c */

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "types.h"

#define LIB_CACULATE_PATH "./libcaculate.so"

typedef int32 (*CAC_FUNC)(int, int);

int32 main()
{
    void *handle;
    uint8 *error;
    CAC_FUNC cac_func = NULL;

    /* open ddl */
    handle = dlopen(LIB_CACULATE_PATH, RTLD_LAZY);
    
    if (NULL == handle) 
    {
        fprintf(stderr, "%s\n", dlerror());
        exit(EXIT_FAILURE);
    }

    dlerror();

    /* get function add sub mul div */

    cac_func = (CAC_FUNC)dlsym(handle, "add");
    printf("add: %d\n", (*cac_func)(2,7));

    cac_func = (CAC_FUNC)dlsym(handle, "sub");
    printf("sub: %d\n", cac_func(9,2));

    cac_func = (CAC_FUNC)dlsym(handle, "mul");
    printf("mul: %d\n", cac_func(3,2));

    cac_func = (CAC_FUNC)dlsym(handle, "div");
    printf("div: %d\n", cac_func(8,2));

    /* close ddl */
    dlclose(handle);
    
    exit(EXIT_SUCCESS);
}

Makefile

.PHONE : all

all : libcaculate.so test

libcaculate.so : caculate.o
	gcc -Wall -fPIC -shared $^ -o $@
test: test.o
	gcc -Wall -L./ -rdynamic $^ -o $@ -ldl
test.o : test.c
	gcc -c $<
caculate.o : caculate.c
	gcc -c $<

clean:
	rm -f *.so *.o test
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值