Linux有时我们需要在运行时指定库的路径去加载库,而不是依赖于系统自动动态链接。比如说我们在需要做到动态加载库插件时就会用到动态装载库的特性(比如像lighthttpd和nginx的动态mod功能),Linux提供了函数来帮助我们做到这件事,主要的几个函数为:dlopen,dlsym,dlclose
栗子
假设我们一个项目可能会需要加载不同版本的库v1和v2,我们希望在配置文件中实现可配置加载哪个库,于是我们写出了hello world v1和v2版本,并动态调用:
hello world v1
#include <stdio.h>
void hello() {
printf("hello world! -- v1\n");
}
hello world v2
#include <stdio.h>
void hello() {
printf("hello world! -- v2\n");
}
dlopen.c
#include <stdio.h>
#include <dlfcn.h>
typedef void(*hello_world)();
int main(int argc, char** argv) {
void *handle = dlopen(argv[1], RTLD_LAZY);//dlopen 返回了一个handle用于以后的各项dl操作的对象
if(handle) {
hello_world hello = (hello_world)dlsym(handle, "hello");//利用返回的handle来找函数地址,并把函数地址转换成函数指针,提供调用
if(hello) {
hello();//调用
} else {
printf("%s\n", dlerror());
}
dlclose(handle);
} else {
printf("dlopen %s failed!\n", argv[1]);
}
return 0;
}
编译:
gcc -shared -o hello_v1.so hello_v1.c
gcc -shared -o hello_v2.so hello_v2.c
gcc -o dlopen dlopen.c -ldl
测试:
$ ./dlopen hello_v1.so
hello world! -- v1
$ ./dlopen hello_v2.so
hello world! -- v2