#include <stdio.h>
#include <dlfcn.h>
int main(void) {
// 使用动态加载的编译时必须链接dl库(-ldl),因为动态加载的各种方法都在dl库中
// gcc main.c -o test -ldl
/* 获取错误信息 char * dlerror(void)
* 获取在打开、关闭、使用动态库时发生的错误
* 有错误返回字符串指针,没有错误返回NULL
* */
/* 加载动态库 void * dlopen(const char * __path, int __mode)
* __path 动态库的路径,如果只给文件名不带路径,则根据LD_LIBRARY_PATH环境变量搜索动态库
* __mode 加载方式
* RTLD_LAZY 延迟加载
* RTLD_NOW 立即加载
* 加载成功返回动态库句柄,失败返回NULL
* */
void *handler = dlopen("libmath.so", RTLD_LAZY);
if (handler == NULL) {
fprintf(stderr, "dlopen:%s\n", dlerror());
}
/* 取动态链接库的符号 void * dlsym(void * __handle, const char * __symbol)
* __handle 动态库的句柄
* __symbol 符号(函数名、变量名、结构体名....)
* 加载成功符号地址,失败返回NULL
* */
int (*p_add)(int, int) = dlsym(handler, "add");
if (p_add == NULL) {
fprintf(stderr, "dlsym:add:%s\n", dlerror());
}
int (*p_sub)(int, int) = dlsym(handler, "sub");
if (p_add == NULL) {
fprintf(stderr, "dlsym:sub:%s\n", dlerror());
}
void (*p_show)(int, char, int, int (*)(int, int)) = dlsym(handler, "show");
if (p_show == NULL) {
fprintf(stderr, "dlsym:show:%s\n", dlerror());
}
int a = 10, b = 20;
p_show(a, '+', b, p_add);
p_show(a, '-', b, p_sub);
/* 卸载动态库 int dlclose(void * __handle)
* __handle 动态库的句柄
* 卸载成功返回0,失败返回非零
* 卸载动态库之后,动态库不一定会立即从内存中删除,因为其他程序也许还在使用动态库,但是当前程序通过dlopen获取到的句柄会立即失效
*
* */
if (dlclose(handler)) {
fprintf(stderr, "dlclose:%s\n", dlerror());
}
return 0;
}