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