void* dlopen(const char* filepath, int mode)
加载动态库
int mode
只能使用下面2
个宏
:
宏 | 说明 |
RTLD_NOW | resolve all undefined symbols before dlopen() returns and fail if this cannot be done |
RTLD_LAZY | resolve undefined symbols as code from the dynamic library is executed |
const char* filepath
用于指定要加载的动态库
的路径。
const char* filepath
中如果含有/
,表明该该路径是相对路径
或绝对路径
,这是就用该路径加载动态库。
const char* filepath
中如果不含有/
,表明它只是个文件名
,这时候,就要进行搜索。至于如何搜索, 由于不同的操作系统使用了不同的loader
,搜索的逻辑不尽相同。但都会去LD_LIBRARY_PATH
环境变量指定的路径中搜索。
操作系统 | loader | 参考 |
---|---|---|
GNU/Linux | /lib/ld-liunx.so.N /lib64/ld-linux-x86-64.so.N | |
BSD-based |
| |
macOS | /usr/lib/dyld |
若成功,则返回非NULL
。
若失败,则返回NULL
。
step1、编写一个C源程序add.c
,其内容如下
int add(int a, int b) {
return a + b;
}
step2、使用gcc命令将add.c
编译为动态库
gcc -shared -fPIC -o libadd.so add.c
step3、编写一个C源程序main.c
,其内容如下
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char* argv[]) {
if (1 == argc) {
perror("please provide a library path");
return 1;
}
void* handle = dlopen(argc[1], RTLD_LAZY);
if (NULL == handle) {
printf("load %s error, %s\n", argc[1], dlerror());
return 1;
}
printf("load %s success.\n", argc[1]);
int (*add)(int a, int b);
add = dlsym(handle, "add");
int value = add(2, 3);
printf("add(2, 3) = %d\n", value);
int statusCode = dlclose(handle);
printf("unload %s %s!\n", argc[1], statusCode ? "failed" : "success");
return statusCode;
}
step4、使用gcc命令将mian.c
编译为可执行文件
gcc -o main main.c
step5、运行main
可执行文件
./main libadd.so
运行结果如下:
load libadd.so success.
add(2, 3) = 5
unload libadd.so success.
注意:这种加载动态库
的方式,不需要我们在编译的时候进行链接
用到的动态库
。 相比于动态链接
,这种动态加载更灵活。