动态库的动态链接、打开、调用,使用dlopen、dlsym和dlclose
动态库的动态链接、打开、调用,使用dlopen、dlsym和dlclose 为了使程序方便扩展,具备通用性,可以采用插件形式。采用异步事件驱动模型,保证主程序逻辑不变,将各个业务已动态链接库的形基本的操作方法,式加载进来,这就是所谓的插件。Unix, linux和windows都有提供加载和处理动态链接库的系统调用,非常简单;基本的操作方法动态链接库如何被加载进来?动态
动态库的动态链接、打开、调用,使用dlopen、dlsym和dlclose
为了使程序方便扩展,具备通用性,可以采用插件形式。采用异步事件驱动模型,保证主程序逻辑不变,将各个业务已动态链接库的形基本的操作方法,式加载进来,这就是所谓的插件。Unix, linux和windows都有提供加载和处理动态链接库的系统调用,非常简单;
基本的操作方法
- 动态链接库如何被加载进来?
- 动态链接库如何被调用
举例说明
1.创建一个libCalculator.c文件,有四个很简单的函数,如下
#include <stdio.h>
int add(int a, int b)
{
return (a + b);
}
int subtract(int a, int b)
{
return (a - b);
}
int multiply(int a, int b)
{
return (a * b);
}
int divide(int a, int b)
{
return (a / b);
}
2.使用gcc命令将此文件生成.so动态库
gcc -fPIC -shared libCalculator.c -o libCalculator.so
3.创建一个控制台项目来使用并调用这个库
#include <stdio.h>
#include <dlfcn.h>
//定义函数指针
typedef int (*CalculatorFuncPointer)(int, int);
int main(int argc, const char * argv[]) {
//动态库地址
char *dlib_path = "/Users/VictorZhang/Desktop/Repos/libCalculator.so";
//链接并打开动态库
void *handle = dlopen(dlib_path, RTLD_GLOBAL | RTLD_NOW);
if (handle == NULL) {
fprintf(stderr, "%s\n", dlerror());
} else {
//获取add函数
//注意:函数指针接收的add函数有几个参数和什么返回类型要一致
CalculatorFuncPointer add_func = dlsym(handle, "add");
int add_ret = add_func(10, 20);
printf("add function result : %d \n", add_ret);
//获取subtract函数
//注意:函数指针接收的subtract函数有几个参数和什么返回类型要一致
CalculatorFuncPointer subtract_func = dlsym(handle, "subtract");
int subtract_ret = subtract_func(10, 20);
printf("subtract function result : %d \n", subtract_ret);
//获取multiply函数
//注意:函数指针接收的multiply函数有几个参数和什么返回类型要一致
CalculatorFuncPointer multiply_func = dlsym(handle, "multiply");
int multiply_ret = multiply_func(10, 20);
printf("multiply function result : %d \n", multiply_ret);
//获取divide函数
//注意:函数指针接收的divide函数有几个参数和什么返回类型要一致
CalculatorFuncPointer divide_func = dlsym(handle, "divide");
int divide_ret = divide_func(10, 2);
printf("divide function result : %d \n", divide_ret);
dlclose(handle);
}
return 0;
}
说明:
- 我们的所有操作的相关函数都在#include <dlfcn.h>头文件里
- dlopen函数负责动态链接并打开指定动态库,第一个参数是动态库地址,第二个参数如下解释;
- dlsym函数负责动态加载符号(函数),第一个参数是句柄(由dlopen时返回的),第二个参数就是给定的函数名称
- dlclose函数负责关闭指定句柄的动态库,当该库的使用计数为0时,就会被卸载
dlopen的第二个参数表示解析方式:
RTLD_LAZY 表示使用时才解析函数引用
RTLD_NOW 立即解析函数引用
RTLD_GLOBAL 动态库中定义的符号可被其后打开的其它库解析
RTLD_LOCAL 与RTLD_GLOBAL相反,动态库中定义的符号不能被其打开的其它库重定位,如果没有明确指明,默认是RTLD_LOCAL
RTLD_NODELETE 在dlclose()期间不卸载库,并且在以后使用dlopen()重新加载库时不初始化库中的静态变量。这个flag不是POSIX-2001标准。
RTLD_NOLOAD 不加载库。可用于测试库是否已加载(dlopen()返回NULL说明未加载,否则说明已加载),也可用于改变已加载库的flag,如:先前加载库的flag为RTLD_LOCAL,用dlopen(RTLD_NOLOAD|RTLD_GLOBAL)后flag将变成RTLD_GLOBAL。这个flag不是POSIX-2001标准
超简单的吧,是不是~~~
更多推荐
所有评论(0)