运维开发网

详细介绍了c语言中dlopen和dlsym的用法

运维开发网 https://www.qedev.com 2022-05-02 16:56 出处:网络
这篇文章主要为大家详细介绍了C语言中dlopen和dlsym的使用方式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

这篇文章主要为大家详细介绍了C语言中dlopen和dlsym的使用方式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助


背景

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

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

我们知道cublas是Nvidia提供的,每年都要有人更新动态库。比如今年更新后,动态库头文件改为cublas_v2.h,函数名改为sgemm_v2。这样的操作之后,你不仅要升级库,还要修改已经上线的代码。如果这个sgemm函数在你的源代码中出现N次以上,那就惨了。但是您可以通过以下方式避免这个问题:

// func.h#include lt;stdio.hgt;#include lt;stdlib.hgt;#include lt;cublas_v2.hgt; // 如果你知道确切的函数返回信息,这个对应下面的cublas_func可以自己写。#include lt;dlfcn.hgt;extern std::once_flag cublas_dso_flag;extern void *cublas_dso_handle; struct DynLoad__add { template lt;typename... Argsgt; inline auto operator()(Args... args) -gt; DECLARE_TYPE(add, args...) { using cublas_func = decltype(::add(std::declvallt;Argsgt;()...)) (*)(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_castlt;cublas_funcgt;(p_add)(args...); } }; extern DynLoad__add add;// func.cDynLoad__add add;// main.cc#include lt;stdio.hgt;#include lt;stdlib.hgt;#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 calculate . c-o libcaculate . so


调用dlopen#include lt;dlfcn.hgt;void *dlopen(const char *filename, int flag);char *dlerror(void);void *dlsym(void *handle, const char *symbol);int dlclose(void *handle);

Dlopen是加载动态链接库。标志可以在不同的模式下设置(RTLD_LAZY挂起判定,然后在必要时求解符号。RTLD_NOW立即决定,在返回之前释放所有未决定的符号。),dlopen可以返回动态库的句柄,dlsym是获取动态库中的具体函数名或变量名。Dlopen是关闭动态库。

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

gcc -rdynamic -o main main.c -ldl


总结

本文到此为止。希望能帮到你,也希望你能多多关注源搜网的更多内容!


0

精彩评论

暂无评论...
验证码 换一张
取 消