主要涉及到的函数如下:
#include <dlfcn.h>
void *dlopen(const char *file, int mode);
void *dlsym(void * restrict handle, const char * restrict name);
int *dlclose(void *handle);
char *dlerror();
dlopen():打开指定的动态链接库文件,并将它读入内存,返回一个句柄给调用进程。该函数主要用于加载库中的符号
file: 库文件名称
mode:
按解析时间:
RTLD_LAZY: 暂缓决定,等有需要时再解析出符号,仅对函数引用有效,变量总是立即解析
RTLD_NOW: 立即决定,返回前解出所有符号,若有符号解析不出来,会返回NULL
按作用范围:
RTLD_GLOBAL:动态库中定义的符号可被其后打开的其他库重定位
RTLD_LOCAL:与RTLD_GLOBAL作用相反,动态库中定义的符号不能被其后打开的其它库重定位,缺省为RTLD_LOCAL。
dlsym(): 根据动态链接库操作句柄与符号,返回符号对应的地址,可以是函数也可以是变量
handle:dlopen返回的动态链接库句柄
name:符号名称,可为函数名或变量名称
dlclose(): 关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载
dlerror(): 当动态链接库执行失败(包括dlopen, dlsym和dlclose)时,本函数返回出错信息,返回NULL表示执行成功
示例源码:
#include <dlfcn.h>
#include <stdio.h>
typedef void (*hello_t)();
int main()
{
void * lib = dlopen("test.so", RTLD_LAZY);
if(lib == NULL)
{
printf("dlopen failed_%s\n", dlerror());
return;
}
hello_t hello = (hello_t)dlsym(lib, "hello");
int * a1 = (int *)dlsym(lib, "a");
printf("%d\n", *a1);
hello();
dlclose(lib);
}
编译记得加上-ldl:gcc dlopen.c -ldl
运行结果:
12
helloworld
test.so的源码如下:
#include <stdio.h>
int a = 12;
void hello()
{
printf("helloworld\n");
}
gcc -c -fPIC test.c
gcc -shared -fPIC -o test.so test.o