dlopen和 dlsym的使用方式

2023-10-30

背景

为了把不同的逻辑解耦,一般会把各个业务封装成动态库,然后主逻辑去调用各个动态库。这里有个问题是,为什么以前我们都是通过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* tmp= dlsym(handle, "add");
    FUNC func = reinterpret_cast<FUNC>(tmp);
    printf("add: %d\n", (*func)(2,7));
    //printf("add: %d\n", func(2,7)); 这两种写法都正确,函数指针的解引用符号等于自己不做处理,建议用第二种写法,直观。
    //关闭动态链接库
    dlclose(handle);
}

gcc -rdynamic -o main main.c -ldl

参考链接

https://www.cnblogs.com/Anker/p/3746802.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

dlopen和 dlsym的使用方式 的相关文章

  • Qt 图表和数据可视化小部件

    我已经安装了 Qt 5 7 来尝试 Qt 图表和 Qt 数据可视化 但我在 Qt Designer 和 Qt Creator 中都找不到新的小部件 有什么建议我应该做什么才能让新的小部件出现在设计器中 我今天遇到了完全相同的问题 默认情况下
  • Linq - 从表达式 创建表达式

    我有一个谓词Expression
  • 自动映射器多对多 stackoverflowException

    我遇到以下映射的堆栈溢出 Mapper CreateMap
  • 为什么子函数不销毁GtkWindow?

    这是我的代码 void window first void enter window2 GtkWidget w gpointer data void quit GtkWidget w gpointer data void quit int
  • 无法加载程序集问题

    我收到以下错误 无法加载程序集 错误详细信息 System BadImageFormatException 无法加载文件或程序集 文件 或其依赖项之一 该程序集是由比当前加载的运行时更新的运行时构建的 无法加载 该程序集是使用 Net Fr
  • Linq 合并列表

    我的课 public class Foo public int A get set public List
  • 如何减少 MinGW g++ 编译器生成的可执行文件的大小?

    我有一个简单的 Hello world C 程序 在 Win XP 下由 MinGW g 编译器编译为 500kB 可执行文件 有人说这是由于iostream的库和静态链接libstdc dll Using s链接器选项有点帮助 减少了 5
  • 应用程序处于中断模式。您的应用程序已进入中断状态,

    我发现自己遇到了同样的问题here https stackoverflow com questions 36204009 disable break mode page in vs2015 我在 dll 中使用 Windows 窗体 这是针
  • 调用异步方法在视图模型的构造函数中加载数据有警告

    我的视图包含一个 ListView 它显示来自互联网的一些数据 我创建一个异步方法来加载数据并在我的视图模型的构造函数中调用该方法 它有一个警告提示我现在使用await关键字 还有其他解决方案可以在构造函数中异步加载数据吗 有几种可以应用的
  • 我在使用 ado.net 时收到错误 Argument 2 may not be pass with ref keywords

    int t 0 cmd Parameters AddWithValue Res ref t 我在第二行收到错误 参数 2 不能与 ref 关键字一起传递 您只能通过引用传递参数ref if the 范围 is a ref参数也是如此 Add
  • 当需要不同数量和类型的参数时如何创建操作委托列表

    我们有一组大约两打的类 它们继承自具有抽象 Validate 方法的基类 当然 每个类都有不同的验证需求 但它们之间的不同组合需要规则 因此 正如您可以想象的那样 这导致了大量代码重复 例如 A 类需要规则 1 3 6 和 9B 类需要规则
  • 如何在 C# 中更改公共 IP 地址

    我正在创建一个 C winform 应用程序 我想在其中更改公共 IP 地址 而不是像 Hotspot Shield ZenMate OpenVPN 等那样更改 IPv4 地址 我已经检查了以下链接 但没有找到足够的帮助 所以我发布了这个问
  • 从 DataRow 单元格解析 int [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 如何从 DataRow 单元格解析 int 值 Int32 Parse item QuestionId ToString 这段代码可以工作 但看
  • 如何检测应用程序正在运行的 .NET 版本?

    我尝试使用Environment Version ToString 确定目标计算机上正在使用什么 NET 框架 但安装了 4 0 版本时 它说我正在使用 NET 2 0 如何检测目标计算机上正在运行的 NET Framework 版本 En
  • 如何从 Access 数据库中读取“是/否”值作为布尔值?

    帮我找回YES NO来自 MS Access 的布尔格式数据类型 我尝试解析它 但它总是返回 false 更新 实际上不是问题抱歉 它确实接受 YES NO 作为布尔值 OleDbconnection dbConnect new OleDb
  • Xcode 7 调试器不会中断内联标头函数

    过去五年我一直在各种 C 项目中使用 Xcode 没有出现这个问题 今天 我打开了一个较旧的项目 大约 2 年前 并尝试通过在该函数中放置一个活动断点来调试头文件中的内联函数 由于某种原因 调试器不会中断此代码 但是 如果我在调用该函数的
  • 卸载程序

    我正在尝试使用此代码卸载程序 但它似乎不起作用 我尝试过其他答案 但似乎也不起作用 有人可以帮助我吗 我正在尝试按给定名称 displayName 卸载该程序 例如 我给出 displayName Appname 那么此代码应该从我的计算机
  • 当我的进程被终止时到底会发生什么?

    我有一个包含本机代码和托管代码的混合进程 在 Windows Server 2003 上运行 当我从进程资源管理器中终止进程时 它会进入 100 cpu 的状态 并在消失之前保持这种状态一段时间 有时甚至 10 分钟 在此期间我无法 杀死
  • 从对列表创建邻接列表类型结构

    在 C 中 我有 class Pair int val1 int val2 我有一个来自以下来源的配对列表 List
  • 实体框架代码首次日期字段创建

    我正在使用实体框架代码优先方法来创建我的数据库表 下面的代码 创建一个DATETIME数据库中的列 但我想创建一个DATE柱子 DataType DataType Date DisplayFormatAttribute ApplyForma

随机推荐

  • 【blender建模功能】03 倒角工具

    blender 03 倒角工具 基操 宽度类型 其他参数 倒角问题 顶点倒角 1 基础操作 2 宽度类型 3 其他参数 3 1 材质编号 3 2 平滑 3 2 1 自动光滑 3 2 2 硬化法线 3 3 钳制重叠 3 4 外衔接 内衔接 3
  • UE4联网2——视角同步

    在做完子弹的同步后发现和客户端和服务器的玩家的仰角是不同步的 所以在角色代码中加入tick函数更新玩家的仰角pitch 这里我们需要用到一个变量RemoteViewPitch 这是在pawn中定义的已经复制的公有变量 rpc 值得注意的是它
  • 忽略大小写的字符串比较

    问题描述 一般我们用strcmp可比较两个字符串的大小 比较方法为对两个字符串从前往后逐个字符相比较 按 ASCII 码值大小比较 直到出现不同的字符或遇到 0 为止 如果全部字符都相同 则认为相同 如果出现不相同的字符 则以第一个不相同的
  • vue3引用ElementPlus出错|如何在vue中引用TypeScript

    具体错误 直接套用elementplus官方文档里的模版 报错 Module parse failed Unexpected token You may need an additional loader to handle the res
  • 运放噪声如何计算?

    一 噪声 运放的噪声分为 1 电压噪声en v 2 电流噪声在电阻Rs和R1 R2上产生的等效噪声en i 3 电阻的热噪声enr 总输入噪声计算公式 en in sqrt env 2 eni 2 enr 2 总输出噪声计算公式 en ou
  • [第七届蓝帽杯全国大学生网络安全技能大赛 蓝帽杯 2023]——Web方向部分题 详细Writeup

    Web LovePHP 你真的熟悉PHP吗 源码如下
  • 【C++】C++入门

    目录 一 C 关键字 二 命名空间 2 1命名空间的定义 2 2命名空间的使用 2 2 1加命名空间名称和作用域限定符 2 2 2使用using 将命名空间中某个成员引入 2 2 3使用using namespace将命名空间引入 三 C
  • 【KnowledgeBase】CLIP多模态代码试玩

    文章目录 前言 一 CLIP整体流程简述 二 代码试玩 参考 前言 多模态CLIP的推理部分代码简单试玩一下 致敬大佬的CLIP 论文链接 Learning Transferable Visual Models From Natural L
  • JS中的“&&”与“&”和“

    在JavaScript中 和 是逻辑运算符 和 是位运算符 四个运算符主要区别是运算方法不一样 1 JavaScript中的位运算符 运算方法 两个数值的个位分别相与 同时为1才得1 只要一个为0就为0 举个例子 31 2 结果为2 理由
  • python-报错

    报错 异常名称 描述 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行 通常是输入 C Exception 常规错误的基类 StopIteration 迭代器
  • JS 统计字符

    var str id content value replace r n g n var length t str length
  • 使用Koa2进行Web开发(一)

    这篇文章是我正在进行写作的 新时期的Node js入门 的一部分 Connect Express与Koa 为了更好地理解后面的内容 首先需要梳理一下Node中Web框架的发展历程 Connect 在connect官方网站提供的定义是 Con
  • Python实现贝叶斯优化器(Bayes_opt)优化卷积神经网络回归模型(CNN回归算法)项目实战

    说明 这是一个机器学习实战项目 附带数据 代码 文档 视频讲解 如需数据 代码 文档 视频讲解可以直接到文章最后获取 1 项目背景 贝叶斯优化器 BayesianOptimization 是一种黑盒子优化器 用来寻找最优参数 贝叶斯优化器是
  • 从枚举类型的ordinal()方法说起

    文章背景 本周有一个开发任务涉及到了枚举类型的修改 需要对枚举类型新增一项 在新增的时候我没有加在已有项的最后面 而是在中间随便找了个位置 其实也不是很随便 我是根据语义关联性觉得放在某一项后面比较合适 没想到的是 我的无心之举经造成了大
  • 安装centos 8

    安装centos 8 首先下载centos 8镜像 地址 http mirrors aliyun com centos 8 isos x86 64 这里选择了boot版本 boot版与完整版的区别是体积小 通过网络源安装 下载完成大概有70
  • Solidity与dapp开发学习记录4

    目录 函数修饰符进阶 Payable修饰符 运用 取款 Withdraws 运用 准备好设计僵尸对战 随机数 Random Numbers 通过keccak256生成随机数 此方法容易受到不诚实节点的攻击 如何在以太坊中安全地生成随机数 运
  • BASE64Encoder及BASE64Decoder的正确用法

    一直以来Base64的加密解密都是使用sun misc包下的BASE64Encoder及BASE64Decoder的sun misc BASE64Encoder BASE64Decoder类 这人个类是sun公司的内部方法 并没有在java
  • 腾讯云搭建邮局

    想在个人电脑上面搭个邮局临时用一下 没有想到宽带的端口全部被封了 25 110 143本来以为不能发就算了 收也不行了 完全没有办法用 还好腾讯云有按月开通的 先开通一个月试试 花了三十块 开了一个 轻量应用服务器 这里安全方面 没有什么要
  • 系统架构设计高级技能 · 层次式架构设计理论与实践

    现在的一切都是为将来的梦想编织翅膀 让梦想在现实中展翅高飞 Now everything is for the future of dream weaving wings let the dream fly in reality 点击进入系
  • dlopen和 dlsym的使用方式

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