温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C语言中dlopen和dlsym如何使用

发布时间:2022-03-28 09:10:00 来源:亿速云 阅读:168 作者:iii 栏目:开发技术

这篇文章主要介绍“C语言中dlopen和dlsym如何使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C语言中dlopen和dlsym如何使用”文章能帮助大家解决问题。

    背景

    为了是不同的逻辑解耦,一般会把各个业务封装成动态库,然后主逻辑去调用各个插件。这里有个问题是,为什么以前我们都是通过include第三方的头文件,然后通过连接器实现,现在却要利用dlopen呢?考虑以下情况,比如我们要用cublas这个库的sgemm函数。

    #include "cublas.h"
    int main()
    {
    	cublas:: Mat a, b;
    	cublas::sgemm(a,b);
    }

    我们知道cublas是英伟达提供的,人家每年都要更新动态库的,比如今年更新后,动态库的头文件改了cublas_v2.h, 函数名改为sgemm_v2, 这样一顿操作后,你不仅要升级库,也要修改已经上线的代码,假如这个sgemm函数在你源码中出现了n多次,这将是一个灾难。但是通过下面的方式你就可以避免这个问题:

    // func.h
    #include <stdio.h>
    #include <stdlib.h>
    #include <cublas_v2.h> // 如果你知道确切的函数返回信息,这个对应下面的cublas_func可以自己写。
    #include <dlfcn.h>
    extern std::once_flag cublas_dso_flag;
    extern void *cublas_dso_handle;
      struct DynLoad__add {                                                
        template <typename... Args>                                             
        inline auto operator()(Args... args) -> DECLARE_TYPE(add, args...) 
        { 
          using cublas_func =  decltype(::add(std::declval<Args>()...)) (*)(Args...);         
          std::call_once(cublas_dso_flag, []() {                                
            cublas_dso_handle = dlopen("./libcublas.so", RTLD_LAZY);       
          });                                                                   
          static void *p_add = dlsym(cublas_dso_handle, "add");          
          return reinterpret_cast<cublas_func>(p_add)(args...);            
        }                                                                       
      };                                                                        
      extern DynLoad__add add;
    // func.c
    DynLoad__add add;
    // main.cc
    #include <stdio.h>
    #include <stdlib.h>
    #include "func.h"
    int main()
    {
        add(2,7));
    }
    根据上面的代码可以看到,只要你每次修改func.h文件的动态库路劲和函数名就可以了,其他用到的add函数根本不需要再去修改。真是很方便,上面的代码参考paddle的源码:paddle/fluid/platform/dynload/cublas.h

    demo

    生产动态库

    int add(int a,int b)
    {
        return (a + b);
    }
    int sub(int a, int b)
    {
        return (a - b);
    }

    gcc -fPIC -shared caculate.c -o libcaculate.so

    调用dlopen

    #include <dlfcn.h>
    void *dlopen(const char *filename, int flag);
    char *dlerror(void);
    void *dlsym(void *handle, const char *symbol);
    int dlclose(void *handle);

    dlopen是加载动态链接库,flag可以设置不同的模式(RTLD_LAZY 暂缓决定,等有需要时再解出符号, RTLD_NOW 立即决定,返回前解除所有未决定的符号。), dlopen可以返回动态库的句柄,dlsym是获取动态库中的具体函数名或者变量名。dlopen是关闭动态库。

    #include <stdio.h>
    #include <stdlib.h>
    #include <dlfcn.h>
    typedef int (*FUNC)(int, int);
    int main()
    {
        void *handle;
        char *error;
        FUNC func = NULL;
        //打开动态链接库
        handle = dlopen("./libcaculate.so", RTLD_LAZY);
        //获取一个函数
        *(void **) (&func) = dlsym(handle, "add");
        printf("add: %d\n", (*func)(2,7));
        //关闭动态链接库
        dlclose(handle);
    }

    gcc -rdynamic -o main main.c -ldl

    关于“C语言中dlopen和dlsym如何使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI