动态库的动态链接、打开、调用,使用dlopen、dlsym和dlclose

come form : https://blog.csdn.net/u013538542/article/details/72676460

动态库的动态链接、打开、调用,使用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标准

猜你喜欢

转载自blog.csdn.net/zmjames2000/article/details/88114392
今日推荐