为了使程序方便扩展,具备通用性,可以采用插件形式。采用异步事件驱动模型,保证主程序逻辑不变,将各个业务已动态链接库的形式加载进来,这就是所谓的插件。linux提供了加载和处理动态链接库的系统调用,非常方便。
创建动态链接库
例如将如下程序test.c
编译为动态链接库,程序如下:
#include <stdio.h>
#include <unistd.h>
int add(int a,int b){
return (a + b);
}
int sub(int a,int b){
return (a - b);
}
int mul(int a,int b){
return (a * b);
}
int div(int a,int b){
if(b != 0){
return (a / b);
}
return 0;
}
注意:这里的编译指令无法编译Cpp文件
gcc -fPIC -shared test.c -o test.so
dlopen、dlsym函数介绍
#import <dlfcn.h>
// dlclose来卸载打开的库。
extern int dlclose(void * __handle) __DYLDDL_DRIVERKIT_UNAVAILABLE;
// dlerror返回出现的错误,
extern char * dlerror(void) __DYLDDL_DRIVERKIT_UNAVAILABLE;
/*
RTLD_LAZY 表示:使用延迟绑定,当函数第一次被用到时,才进行绑定,即 PLT 机制。
优点:加载速度快
缺点:如果后面有符号绑定出错将难以发现
RTLD_NOW 当模块加载时,即完成所有的函数绑定工作。
优点:慢
缺点:有错误及时发现
*/
// dlopen以指定模式打开指定的动态连接库文件,将其加载到进程地址空间中,并返回一个句柄给调用进程,
extern void * dlopen(const char * __path, int __mode) __DYLDDL_DRIVERKIT_UNAVAILABLE;
// dlsym通过句柄和连接符名称获取函数名或者变量名,
extern void * dlsym(void * __handle, const char * __symbol) __DYLDDL_DRIVERKIT_UNAVAILABLE;
测试代码
#include <stdio.h>
//依赖的头文件
#include <dlfcn.h>
#include <stdlib.h>
//动态链接库路径
#define LIB_TEST_PATH "路径/test.so"
//声明函数指针
typedef int(*CAC_FUNC)(int,int);
int main(int argc, const char * argv[]) {
// 句柄
void *handle;
// error
char *error;
// 声明函数指针
CAC_FUNC cac_func = NULL;
//打开动态链接库
handle = dlopen(LIB_TEST_PATH,RTLD_LAZY);
if(!handle){
// 打开失败
printf("handle is null!\n");
return -1;
}
//是否有错误
char* szerror = dlerror();
if(szerror != NULL){
printf("error message:%s\n",szerror);
dlclose(handle);
return -1;
}
//获取一个函数
cac_func =(CAC_FUNC)dlsym(handle,"add");
if(cac_func != NULL){
int num = cac_func(5,5);
printf("add_num:%d\n",num);
}
cac_func = (CAC_FUNC)dlsym(handle,"sub");
if(cac_func != NULL){
int num = cac_func(6,5);
printf("cac_num:%d\n",num);
}
cac_func = (CAC_FUNC)dlsym(handle,"mul");
if(cac_func != NULL){
int num = cac_func(5,5);
printf("mul_num:%d\n",num);
}
cac_func = (CAC_FUNC)dlsym(handle,"div");
if(cac_func != NULL) {
int num = cac_func(6,2);
printf("div_num:%d\n",num);
}
//关闭动态链接库
dlclose(handle);
cac_func = NULL;
return 0;
}
运行结果
add_num:10
cac_num:1
mul_num:25
div_num:3
Program ended with exit code: 0
对于oc也是一样的,可以通过 dlopen 加载动态库的可执行文件.
网友评论