学习记录:使用Qt在动态库之间实现信息传递
这是一篇学习记录关于如何在动态库之间进行数据传递。动态库在程序开发中的优势很明显可以极大提高开发效率降低模块之间耦合度但动态库之间实现数据交互也是常见需求。在Qt中实现动态库之间的数据交换有多种方式基于信号和槽机制是主要方式之一。信号和槽机制通常在类之间使用但在Qt的动态库之间仍然可以使用基于此机制的具体实现方案也同样有多种方式比如可以直接在主程序中包含动态库头文件在编译时连接动态库就可以直接进行库之间的信号传递这是Qt最常用的、也是最简单的一种动态库调用方法。也可以使用QLibrary加载动态库但任需要包含动态库头文件并在动态库中以C风格导出接口函数供主程序调用创建动态库对象。还有一种是利用Qt插件实现具体不再赘述。以上实现方式其实都没有离开Qt的信号和槽机制。不可否认信号和槽机制为程序开发提供了极大方便简化了程序开发但一个不可避免的限制就是主程序和动态库的开发不能离开Qt操作。如果对其它动态库有这样的需求实现这种方式仍然有其局限。因此要想这种需求实现能有更大范围的适应性还是得考虑C和C最初的实现机制。C和C没有信号和槽机制它的动态库之间的数据传递是通过回调函数实现的以下便是对回调函数实现的具体学习记录。在C中能够实现回调函数的基础是函数名同样是一个指针它也同样可以作为参数在函数之间进行传递。或许再解释一下对回调这个词的理解。回调字面意思像是回头调用实际上是在对象A中定义一个对象B对象A可以直接访问B中公有成员这是很自然的但是在B中并不能直接访问A这是不允许的逻辑上也不可实现因为A在B中是不可见的。但是我们不可避免会存在当B中的工作执行完成之后需要告知A这样的需求而实现这样需求的操作就是回调即在A创建了B在B中实现对A的调用。从上面对回调的解释可以发现在动态库之间实现信息传递与回调是一样的。我们在主程序中加载了动态库但要在动态库中向主程序传递信息好比主程序就是对象A动态库是对象B。如果没有回调一般情况下动态库是不可能访问主程序中的函数的那么动态库也就无法向主程序传递信息。我们前面已经说了上述需求可以通过回调来实现那么回调具体在动态库之间是如何操作的呢这里需要注意一点类和类之间同样存在回调只是具体实现操作相对简单一点而在动态库之间稍微麻烦一点。我们以一个简单的操作链路来描述这一操作过程它的核心思想就是传递函数指针。首先我们在动态库B中导出一个可供主程序A访问的函数函数名称就叫zhuce()其功能就是把A中的一个函数指针传递给动态库B然后在A中调用zhuce()函数将A中的一个函数比如caozuo()。它的函数名caozuo作为zhuce()的参数。zhuce()函数的具体实现代码是在动态库B中编写的其功能就是在A调用该函数时将传进来的参数caozuo函数的指针存下来所以在B中还需要定义一个函数类型指针变量fun_address用于存放caozuo的指针。在B获得函数caozuo的指针后也就代表A成功在B中注册了函数caozuo。那么在B中则可以通过fun_address这个存放函数指针的变量来执行函数caozuo的具体操作了。这也就实现了在B中调用A的函数的要求通过向fun_address代表函数caozuo传递参数也就实现了向A传递信息。以上详细阐述了回调实现的核心思想下面给出具体一个实现案例做进一步说明。首先建立一个共用的头文件用于声明一些主程序和动态库共用的定义这样做只是为了简化代码编写这些定义也可而在主程序和动态库编写时分别设置但需要保持形式一致。typedef void (*NotifyCallBackClose) (void *,int code, const QString msg);typedef QWidget* (*OpendllFunction)(QWidget *,QStringList);typedef void (*RegisterClosefunction)(NotifyCallBackClose,void *);extern NotifyCallBackClose outfunctionClose;//存放回调函数指针extern void * outObject;//在这个头文件中给出了5个定义NotifyCallBackClose表示回调函数的类型它的形式就是上文提到的caozuo()函数。NotifyCallBackClose类型是一个没有返回值但自带3个参数的函数3个参数分别是无类型指针、整型、字符串。NotifyCallBackClose类型的形式必须与caozuo()函数保持一致这个需要根据实际情况进行设计。OpendllFunction表示打开动态的函数类型这个函数类型与回调无关此处只是为了导出一个函数供主程序调用后创建动态库实例。它返回一个QWidget指针带QWidget 指针和QStringList两个类型参数。RegisterClosefunction表示注册函数类型它的形式就是上文中的zhuce()函数这是一个没有返回值带有2个参数的函数2个参数分别是NotifyCallBackClose类型和无类型指针。从这个函数类型就可以看出主程序注册函数时将NotifyCallBackClose类型的函数指针传递了出去同时传递了一个无类型指针。这里先说一下为什么要传递一个无类型指针它不是必须的但传递它的目的是为了便于对主程序中的类对象进行访问。也就是说这个无类型指针其实就是主程序的类对象地址。在上述头文件中还声明了两个全局变量这个含义就很简单outfunctionClose用于存放回调函数的地址outObject用于存放主程序的类对象地址。在此处不能对全局变量进行初始化否则在多个.cpp文件包含该头文件时会产生多个全局变量副本全局变量不唯一造成访问混乱。使用时只需在一个.cpp文件中进行初始化即可。动态库的头文件具体实现如下核心是声明两个导出函数供主程序调用。openOrbitSimulateWin函数与OpendllFunction类型保持一致主程序利用OpendllFunction来解析动态库中的openOrbitSimulateWin函数。registerCallBackClose与RegisterClosefunction类型一致主程序利用RegisterClosefunction来解析动态库中registerCallBackClose函数。#include “上述公共头文件”class ORBITSIMULATE_EXPORT OrbitSimulate: public QMainWindow{}extern C{ORBITSIMULATE_EXPORT OrbitSimulate * openOrbitSimulateWin(QWidget *p,QStringList args);ORBITSIMULATE_EXPORT void registerCallBackClose(NotifyCallBackClose cb,void * co);}动态库的.cpp文件实现如下。文件中首先对两个全局变量进行初始化然后是对两个导出函数的具体实现。openOrbitSimulateWin函数用于创建动态库实例并将实例对象返回给主程序。registerCallBackClose函数用于接收回调函数的地址和主程序对象的地址分别存放在两个全局变量中。最后在动态库类的析构函数中我们通过outfunctionClose指针调用来回调函数并将主程序对象指针和其它定义的参数传回去。outfunctionClose可以在类的任何成员函数中调用此处只是在动态库对象析构时告诉主程序一个信息。NotifyCallBackClose outfunctionClose nullptr;//存放回调函数指针void * outObject nullptr;//OrbitSimulate *openOrbitSimulateWin(QWidget *p, QStringList args){if(args.count() 0)//调用此库时必须传入至少一个数据库路径参数return new OrbitSimulate(p,args.at(0));//新建一个实例elsereturn nullptr;}void registerCallBackClose(NotifyCallBackClose cb,void * co){outfunctionClose cb;outObject co;}OrbitSimulate::~OrbitSimulate(){delete ui;if(outfunctionClose ! nullptr)//outfunctionClose只是回调函数的地址具体是在外部实现的outfunctionClose(outObject,0,OrbitSimulate);//}主程序相关实现代码如下。下面代码是动态库的解析和回调函数注册函数解析的几个必要条件一是知道动态库的路径用QLibrary 加载动态库二是知道需要解析的函数的名称和类型公用头文件中对动态库导出的函数类型进行了定义此处直接使用函数名称则必须要提前知道三是回调函数dealLibClose的形式必须与NotifyCallBackClose保持一致具体实现在主程序中。QLibrary * loadlib new QLibrary;loadlib-setFileName(“动态库路径”);OpendllFunction openlib (OpendllFunction)loadlib-resolve(“openOrbitSimulateWin”);QWidget * newWidget openlib(this,args);RegisterClosefunction registerCloseFun (RegisterClosefunction)loadlib-resolve(“registerCallBackClose”);registerCloseFun(dealLibClose,this);//注册函数供动态库调用可能存在的几个问题一、回调函数必须是静态的。在上述实现中被传递的回调函数必须是静态的可以是全局静态函数也可以是类成员静态函数。二、上述传递主程序对象指针的目的。我们知道静态函数不能访问主程序类中的普通成员。当需要在回调函数中执行一些复杂操作时将不可避免需要操作主程序对象。传递主程序对象指针的目的就是为了能够在回调函数中实现对主程序成员对象的访问。在回调函数中只需要将传递的无类型指针强制转换为主程序类的类型即可通过该指针访问成员对象。三、可能存在内存泄漏问题。在上述代码中如果主程序对象已经释放动态库再调用回调函数时这时传递的指针是非空的因为动态库传回的指针值是存放在动态库内部的全局变量中的动态库未释放时任然有值。回调函数将会得到一个非空指针而实际上这个指针指向的对象已经释放继续操作将导致非法访问程序直接崩溃。这就是上述代码存在的风险指针使程序更加灵活但也带来了风险。在这种情况下回调函数中是无法通过该指针来判断指针是否可用的。那么该如何来避免这种风险呢我们知道静态成员是在程序的main函数退出后最后释放的因此我们可以使用一个静态变量来标记一个对象是否被释放。在对象的析构函数中对该静态变量进行赋值在静态函数中通过该变量值来判断对象是否被释放从而避免非法访问风险。

相关新闻

VMware安装Windows 11全攻略:绕过TPM与性能优化

VMware安装Windows 11全攻略:绕过TPM与性能优化

1. 准备工作:环境与工具清单在VMware Workstation 16 Pro上安装Windows 11前,我们需要准备以下关键组件。这个环节往往被新手忽略,但实际决定了后续安装的成败。1.1 硬件需求核查主机CPU需支持虚拟化技术(Intel VT-x/AMD-V&#x…

2026/7/26 18:11:32 阅读更多 →
BiliTools终极指南:3步掌握免费跨平台B站视频下载工具

BiliTools终极指南:3步掌握免费跨平台B站视频下载工具

BiliTools终极指南:3步掌握免费跨平台B站视频下载工具 【免费下载链接】BiliTools 本项目已停止维护。 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools 你是否经常在B站(哔哩哔哩)上发现精彩的教学视频、心仪的番剧或…

2026/7/30 17:54:12 阅读更多 →
jemalloc与TLB shootdown性能问题分析与优化

jemalloc与TLB shootdown性能问题分析与优化

1. 问题背景:当jemalloc遇上TLB shootdown第一次在线上环境看到"TLB shootdown"这个监控指标突然飙升时,我和团队花了整整三天才定位到根源。那是一个典型的微服务架构,运行在Linux 5.4内核上,使用jemalloc 5.2.1作为默…

2026/7/29 11:38:16 阅读更多 →

最新新闻

三步彻底解决Windows程序运行问题:Visual C++运行库完整修复指南

三步彻底解决Windows程序运行问题:Visual C++运行库完整修复指南

三步彻底解决Windows程序运行问题:Visual C运行库完整修复指南 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否经常遇到新安装的软件无法启动&…

2026/7/30 18:04:38 阅读更多 →
3步搞定!用Video Download Helper轻松保存任何网页视频

3步搞定!用Video Download Helper轻松保存任何网页视频

3步搞定!用Video Download Helper轻松保存任何网页视频 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否经常遇到想要保存网…

2026/7/30 18:04:38 阅读更多 →
网站 安全 扫描 SEO 排名 因素:CDN配错流失20%收录

网站 安全 扫描 SEO 排名 因素:CDN配错流失20%收录

每天上午九点十五分,独立站运营负责人陈明习惯打开流量统计后台。2025年10月14日那天,异常的数据曲线映入眼帘:原本平稳上升的自然搜索流量在过去十二小时内出现断崖式下跌,核心产品页面的日均访问量从八千人次瞬间跌至不足三百人…

2026/7/30 18:04:38 阅读更多 →
抖音内容批量下载终极指南:5步打造个人专属视频资料库

抖音内容批量下载终极指南:5步打造个人专属视频资料库

抖音内容批量下载终极指南:5步打造个人专属视频资料库 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback suppo…

2026/7/30 18:04:38 阅读更多 →
终极解决方案:5分钟快速安装code-box浏览器插件,告别技术博客复制限制

终极解决方案:5分钟快速安装code-box浏览器插件,告别技术博客复制限制

终极解决方案:5分钟快速安装code-box浏览器插件,告别技术博客复制限制 【免费下载链接】code-box 本插件可以用于CSDN/知乎/脚本之家/博客园/掘金等网站,一键下载文章html或markdown文件;实现无需登录一键复制代码;支持选中代码;或者代码右上角按钮的一键…

2026/7/30 18:04:38 阅读更多 →
Agate虚拟主机配置:多域名站点部署与证书管理技巧

Agate虚拟主机配置:多域名站点部署与证书管理技巧

Agate虚拟主机配置:多域名站点部署与证书管理技巧 【免费下载链接】agate Very simple server for the Gemini hypertext protocol 项目地址: https://gitcode.com/gh_mirrors/aga/agate Agate作为一款轻量级Gemini协议服务器,支持通过虚拟主机配…

2026/7/30 18:03:38 阅读更多 →

日新闻

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:13 阅读更多 →
如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否曾经在浏览…

2026/7/30 0:00:13 阅读更多 →
“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

更多请点击: https://intelliparadigm.com 第一章:AI 教师备课辅助 AI 教师备课辅助系统正逐步成为教育数字化转型的核心支撑工具,它并非替代教师,而是通过语义理解、知识图谱与多模态生成能力,将教师从重复性劳动中解…

2026/7/30 0:00:13 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/29 22:18:20 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻