一、背景
在传统的静态链接过程中,所有程序所需的函数和符号都被编译进最终的可执行文件中。然而,这种方式有一定的限制。当我们需要更新库的版本或者引入新的功能时,就需要重新编译整个程序。这对于大型项目来说是非常耗时和不便的。
为了解决这个问题,动态链接库应运而生。动态链接库是一种独立于应用程序的可执行文件的代码和数据集合,它可以在运行时加载到内存中,并在多个应用程序中共享。这种方式使得库的更新和扩展变得更加灵活和高效。
头文件 <dlfcn.h> ,常用函数有 dlopen、dlsym、dlclose
二、函数介绍
- dlopen()
以指定模式打开动态连接库文件,并返回句柄
extern void *dlopen (const char *__file, int __mode) __THROWNL;
const char *__file : 库文件路径
int __mode : 绑定模式
TLD_LAZY : 表示使用延迟绑定,当函数第一次被用到时才进行绑定。有助于提高加载动态库的速度。
RTLD_NOW : 表示当模块被加载时即完成所有函数的绑定工作,如果有任何未定义的符号引用的绑定工作没法完成,那么就返回错误。
- dlclose()
关掉句柄
extern int dlclose (void *__handle) __THROWNL __nonnull ((1));
- dlsym()
根据动态链接库操作句柄(__handle)与符号(__name), 返回函数指针或变量指针
extern void *dlsym (void *__restrict __handle,
const char *__restrict __name) __THROW __nonnull ((2));
- dlerror()
extern char *dlerror (void) __THROW;
当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功
三、示例
库文件
- 创建 mylib.c
#ifdef __cplusplus
extern "C"{
#endif
double add(double, double);
#ifdef __cplusplus
}
#endif
double add(double a, double b){
return a + b * 2;
}
- 生成库文件
gcc -fpic -shared mylib.c -o mylib.so
-fpic : GCC编译器生成动态链接库(多个目标文件的压缩包)时,表示各目标文件中函数、类等功能模块的地址使用相对地址,而非绝对地址
-shared : 生成动态链接库
创建测试文件
- 创建test.cpp
#include <stdio.h>
#include <dlfcn.h>
typedef double (*calc)(double, double);
int main(){
char *error;
void* handle = dlopen("./mylib.so", RTLD_LAZY);
calc add = NULL;
dlerror();
add = (calc) dlsym(handle, "add");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
return 0;
}
double a = 3;
double b = 4;
double addresult = add(a, b);
printf("add result: %f\n", addresult);
return 0;
}
- 编译
运行时链接动态库
gcc -rdynamic -o test test.cpp -ldl
结果
