使用so动态库时,可以在编译时链接动态库,也可以在代码运行时动态加载so库。本文主要介绍如何动态加载so库。
常用的函数主要有dlopen,dlysm,dlclose,dlerror。
一、函数介绍
1、dlopen函数
void * dlopen( const char * pathname, int mode)
- 功能:打开动态库返回句柄
- pathname:so动态库的路径,可以是相对路径
- mode:选项配置
常用mode | 功能 |
RTLD_LAZY | 在dlopen返回前,对于动态库中存在的未定义的变量(如外部变量extern,也可以是函数)不执行解析,就是不解析这个变量的地址 |
RTLD_NOW | 在dlopen返回前,解析出每个未定义变量的地址,如果解析不出来,在dlopen会返回NULL,错误为: : undefined symbol: xxxx....... |
其他mode详解参考 | https://www.cnblogs.com/ho966/p/17366207.html |
- 返回值:动态库的句柄
2、dlsym函数
void *dlsym(void *handle, const char *symbol)
- 功能:根据给定的符号名称查找对应的符号地址,例如函数名会返回函数地址
- handle:dlopen打开的动态库的句柄
- symbol:需要查找的符号名称
- 返回值:symbol符号地址
3、dlclose函数
int dlclose (void *__handle)
- 功能:关闭__handle句柄
4、dlerror函数
char *dlerror (void)
- 功能:检查上次调用是否成功,成功返回NULL,失败返回出错信息
二、实例
1、编译生成so库
#include <stdio.h>
/* 加 */
int cal_add(int a,int b)
{
return (a + b);
}
/* 减 */
int cal_sub(int a, int b)
{
return (a - b);
}
/* 乘 */
int cal_mul(int a, int b)
{
return (a * b);
}
/* 除 */
int cal_div(int a, int b)
{
return (a / b);
}
编译,生成自定义的 libcalculate.so 库
$ gcc -fPIC -shared calculate.c -o libcalculate.so
2、动态加载so库
动态加载 libcalculate.so 库,获取 cal_add 加法函数并调用
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef int (*FUNC)(int, int);
int main(int argc, char* argv[])
{
void *lib;
FUNC lib_func = NULL;
int temp1, temp2, result;
if (argc != 3) {
printf("param error!!!");
return -1;
}
temp1 = strtol(argv[1], NULL, 10);
temp2 = strtol(argv[2], NULL, 10);
/* 打开动态链接库 */
lib = dlopen("./libcalculate.so", RTLD_LAZY);
if (lib == NULL) {
printf("%s dlopen failed: %s\n", "libcalculate.so", dlerror());
}
/* 获取库函数 */
lib_func = dlsym(lib, "cal_add");
if (!lib_func) {
printf("can't find module symbol: %s\n", dlerror());
}
/* 调用库函数 */
result = lib_func(temp1, temp2);
printf("result: %d\n", result);
return 0;
}
编译应用程序, 需要加上"-ldl"库,才能调用dlopen、dlclose等函数
$ gcc -o test_app main.c -ldl #编译生成 test_app 可执行文件
3、测试结果
./test_app 3 8 #运行应用