实战详细讲解Qt插件plugin的编写与用法

news2024/11/18 2:48:42

目录

1.Qt的插件是什么?优点是什么?

2.实战项目需求

3. 程序设计分析

4.Qt插件的编写

Q_DECLARE_INTERFACE(类名,标识符)

Q_INTERFACES

5.插件的调用

总结感言:


1.Qt的插件是什么?优点是什么?

所谓的插件,只不过是重载了虚函数的dll,这跟抽象工厂类类似,这便是插件的原理。qt的插件可以说是一种动态库

        在函数中,我们导入Interface接口文件,也就是插件接口文件,不需要依赖静态库生成代码,类似C/C++关键字extern。而在最后我们通过系统的API加载dll或者so,这个可以自行百度查阅 “动态库加载的两种方式”。

        这样做的好处:定义开发范式,面向Interface编程,内部封装,模块和整体流程开发分离,提高开发效率。应用场景QtCreator-IDE、WPS、visual studio、Nodepad++等等,都是采用这种开发方式。

2.实战项目需求

        有一个嵌入式的显示屏,需要编写软件来写入数据。显示屏的规约已经有一个文档了,现在需要阅读文档,然后根据显示屏规约,封装按页刷显示屏整体数据接口、封装单独修改指定页名称/型号/数量接口,使用插件方式封装。 封装规约文档部分截图如下

显示屏如下

3. 程序设计分析

具体就不讲那么多了,我只需要根据显示屏规约将特定的字符转化为16进制等方式,通过串口通信发送给显示屏,从而实现控制显示屏的显示

我实现的软件如下

 点击写入后将指定数据写入到显示屏中:

         软件的界面我写好了,现在需要写一个插件将接口都封装好,给我的软件调用,然后将接口返回的值,通过串口通信写入显示屏中

接下来讲解插件的编写

4.Qt插件的编写

创建完成后,看到如下界面

 Qt模板中,默认继承了QGenericPlugin的类,这里我们不需要用到,选择自己写一下抽象类,来继承,然后子类来实现。

我们新建一个头文件,抽象类是不需要实现的,所以新建一个头文件即可

         这里我新建了一个PackDataApi的头文件,然后根据需求加入文档的接口,有四个接口,这些接口是给我的软件调用的。比如说我要修改显示屏的用户名和密码,调用后只需要输入要修改的用户名和密码,接口就会返回特定的字符串给你,你只要在把这些字符串发送显示屏就可以修改显示屏的用户名和密码了。 

还有类外的这两行是干嘛的呢?

#define PackDataApi_iid "PackDataPlugin.packdataapi"

Q_DECLARE_INTERFACE(PackDataApi, PackDataApi_iid)

Q_DECLARE_INTERFACE(类名,标识符)

此宏用于把标识符与类名接口关联起来。这个标识符是唯一的,这个宏通常在被放到一个类被定后的位置。

这个是Qt实现插件必须要有的一个宏, 把标识符与类名接口关联起来。标识符PackDataApi_iid我一般用"工程名.接口类名"来标识,看个人习惯啦,不重复就行

抽象类接口都写好后,回到要实现的子类中,把默认继承的类改为自己实现的抽象类,前面在继承一个QObjecet,如下图所示

 发现还用到了两个宏

#if QT_VERSION >= 0x050000
    Q_PLUGIN_METADATA(IID PackDataApi_iid FILE "PackDataPlugin.json")
#endif // QT_VERSION >= 0x050000
    Q_INTERFACES(PackDataApi)

第一个:Q_PLUGIN_METADATA

这个宏被用于声明元数据,这个元数据是被实例化插件的一部分。
这个宏需要通过对象声明被实例化接口的IID,并且要引用包含元数据内容的文件。
在Qt插件源码里面,应该宏应该只能出现异常。

注意,这个宏只能出现在可以被实例化的类中(不能放在抽象类中)。
FILE是可选参数,他指向一个json文件。
这个json文件要包含在构建目录中(为资源文件),创建插件模板时已经自动生成,并且已经包含在里面了,不然moc会出错。

Q_INTERFACES

此宏告诉Qt哪些接口被类实例了。这个宏通常用于插件的实例

这几个宏是必须要写的,Qt规定好的

然后实现接口即可,加入自定义的函数辅助完成接口的开发,如下所示

 具体实现我就不展示了,主要是理解插件开发的过程

实现后,然后编译,会发现在生成目录下有一个动态库生成,这个就是我们要给程序动态加载调用的库,加载后转化为接口类,调用即可

5.插件的调用

我们编译好插件程序,生成动态库了,接下来怎么调用呢?

调用时只需要动态库和实现接口的头文件即可,拿我的软件程序举例,将生成的动态库复制到程序目录下或者指定目录下。

在把接口头文件加入到程序工程目录当中,然后如下所示

 然后在要加载动态库的文件中包含接口头文件

 然后加载插件

 加载插件代码如下,通用的,注意下加载插件的目录即可

void GlobalHelper::loadPlugins()
{
    QDir pluginsDir(QCoreApplication::applicationDirPath());
    qDebug()<< (QString("正在加载BasePageApi插件,路径[%1]").arg(pluginsDir.path()));
    for(QString fileName: pluginsDir.entryList(QDir::Files)) {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            m_dataApi = qobject_cast<PackDataApi *>(plugin);
            if (m_dataApi) {
                qDebug()<<"BasePageApi插件加载成功!";
                return;
            }
        }
    }
    if(QMessageBox::critical(nullptr, "警告", "BasePageApi插件加载失败!", QMessageBox::Ok)==QMessageBox::Ok) {
        qDebug()<<("BasePageApi插件加载失败!!");
    }
}

这样子就完成调用啦

简单叙述调用过程:1.添加接口头文件  2.加载动态库  3.调用

如果要给别人调用的话,我们只需要写好接口文档,怎么调用即可,接口是干嘛的,参数是什么意思等等。

总结感言:

        qt插件的开发,可以说是动态库的开发,因为调用方式类似,多熟悉一下,利用Qt框架开发很简单的。

        在想想这种调用过程有的熟悉,比如公司买了一堆摄像头,公司要对摄像头进行二次开发,实现自己想要的功能,集成到一套设备里去,然后在卖给用户。

        此时厂商肯定会提供开发文档,并给你SDK包(软件开发工具包),  包里你会发现只有头文件和一堆库文件,没有源文件,因为实现的过程是产商公司保密的,给你看还得了。所以都封装成了库的形式给你调用,如静态库或者动态库。这也是为什么会有库这种东西产生,为了自己写的东西不给别人知道我怎么写的。封装起来保密,这可是自己的知识产权呀!

        还有Qt插件的开发,或者说库的开发是独立的一个模块。一般来说,一个大工程是有很多模块组成的,每个模块开发的人不一样,每个模块不同的人各司其职,模块都开发完后,在整合到起立调用,优化,最终完成一个工程。这样子的优点是开发效率高,各司其职,使软件开发更加独立,程序模块直接独立.......

        就讲解那么多啦,写了几个小时啦,肝不下啦,觉得对你有帮助的点个赞再走⑧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/192262.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

let/const相关的内容(一)

1.let/const的基本使用 在ES5中我们声明变量都是使用的var关键字(variable的缩写)&#xff0c;从ES6开始新增了两个关键字可以声明变量&#xff1a;let、const。 let和const在其他编程语言中都是有的&#xff0c;所以并不是新鲜的关键字&#xff0c;但是他们确实给JS带来了不一…

动态规划设计LeetCode 300. 最长递增子序列 354. 俄罗斯套娃信封问题

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 300. 最长递增子序列 354. 俄罗斯套娃信封问题&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434…

【openGauss】把应用开发中的设置客户端字符编码往细了说

前言 早前写过两篇有关Oracle字符集的文章 【ORACLE】谈一谈Oracle数据库使用的字符集,不仅仅是乱码 【ORACLE】谈一谈NVARCHAR2、NCHAR、NCLOB等数据类型和国家字符集 基本说明了 ”数据字符编码“、”客户端字符编码“、”数据库字符编码“三者的关系&#xff0c;这些关系&a…

磨金石教育摄影技能干货分享|年味就是幸福圆满的味道

时光荏苒&#xff0c;时代变迁。以前是古街古巷&#xff0c;现在是高楼大厦。以前的老街&#xff0c;灯笼满街&#xff0c;烟火气十足。现在的城市商业街中霓虹灯可以展示出各种新年的影像。无论时代如何变迁&#xff0c;无论时光走了多远&#xff0c;我们对春节的期待从未改变…

吴恩达机器学习(二)——机器学习之监督模型之回归模型之线性回归模型

y-hat一般指的就是预测值 线性回归模型实例 构建模型 我们有一个房子的大小size&#xff0c;得到房屋价格&#xff08;price&#xff09;&#xff0c;通过这两个常数就可计算一个输入和输出的函数关系。 f w&#xff0c;b(x(i)) wx(i) b i指的是第几个训练数据 评估模型——…

【教程】browsermob-proxy 基于Java的代理服务 配合selenium使用

【教程】browsermob-proxy 基于Java的代理服务 配合selenium使用 配置依赖 <!-- 代理 配合 selenium进行抓包修改等 --><dependency><groupId>net.lightbody.bmp</groupId><artifactId>browsermob-core</artifactId><version>2.1.5&…

H3C Switch S1848G端口限速

需求&#xff1a;在交换机层面对接入用户的网络流量限速1.交换机信息2.主机限速前2.1本机IP和MAC信息依次打开控制面板\所有控制面板项\网络连接2.2限速前测速使用浏览器打开https://10000.gd.cn/测速3.主机限速后3.1查看主机所在交换机接口点击“网络”-“MAC地址”&#xff0…

【微信小程序】给你的页面加上一个填写进度表

前言在搭建一些与申请相关的微信小程序的时候&#xff0c;用户会遇到需要填写很多表单的情况&#xff0c;面对未知的表单数量&#xff0c;用户往往就会放弃填写申请表格。在此基础上作为开发者的我们常常会收到这样的一个任务——给申请页面加上一个填写进度表。这样不仅可以优…

274. H 指数

274. H 指数一、题目描述二、题目分析三、解题思路3.1 更换H指数定义3.2 二分法枚举H指数一、题目描述 二、题目分析 这道题比较绕&#xff0c;理解题目意思&#xff0c;根据题目的说法&#xff0c;所谓的H指数就是&#xff1a;总共有 h 篇论文分别被引用了至少 h 次。且其余的…

二战阿里巴巴成功上岸,准备了小半年,要个28k应该也算不上很高吧~

先说下我基本情况&#xff0c;本科不是计算机专业&#xff0c;现在是学通信&#xff0c;然后做图像处理&#xff0c;可能面试官看我不是科班出身没有问太多计算机相关的问题&#xff0c;因为第一次找工作&#xff0c;阿里的游戏专场又是最早开始的&#xff0c;就投递了&#xf…

Spring Cloud Alibaba系列三:集成Gateway实现路由管理

文章目录Spring Cloud Alibaba系列三&#xff1a;集成Gateway实现路由管理前言1、改造父项目 pom 文件2、创建 gateway 子 module3、配置yml文件Spring Cloud Alibaba系列三&#xff1a;集成Gateway实现路由管理 spring cloud alibaba 版本对照 spring cloud alibaba 有严格的…

【MPP数据库】TiDB表分区探索与实践

方案背景——为什么要进行分区&#xff1f; 一是老板通Tidb集群每天涉及50张表、2亿多条数据回流&#xff0c;合理使用Hash可以把写入压力打散到不同的TiKV&#xff1b; 二是对于大集团数据做聚合&#xff0c;利用分区裁剪原理&#xff0c;查询时可以充当前置索引&#xff0c…

1月第4周榜单丨飞瓜数据B站UP主排行榜(哔哩哔哩平台)发布!

飞瓜轻数发布2023年1月23日-1月29日飞瓜数据UP主排行榜&#xff08;B站平台&#xff09;&#xff0c;通过充电数、涨粉数、成长指数三个维度来体现UP主账号成长的情况&#xff0c;为用户提供B站号综合价值的数据参考&#xff0c;根据UP主成长情况用户能够快速找到运营能力强的B…

卫星地图——MAP(c++)

卫星地图 题目描述 一张矩形的卫星地图&#xff0c;有M行N列。行列中的0表示空地&#xff0c;1表示有建筑。有3种类型的建筑: L型: 仅在一行上占据连续的若干个格子&#xff0c;长度至少为2&#xff0c;至多为N C型&#xff1a;仅在一列上占据连续的若干个格子&#xff0c;…

春节机票销售大增!航空领域哪些业务风险要注意?

目录 航空领域常见的业务风险 2022年航空业务风险趋势分析 航空领域业务风险欺诈分析 如何防范航空业务风险 针对恶意网络爬虫 针对仿冒登录与内控风险 安全技术 春节旅游与出行数据陆续出炉。中国民航局数据显示&#xff0c;2023年1月21日至27日&#xff08;农历除夕至…

Linux - Linux系统

一、Linux系统Linux&#xff0c;全称GNU/Linux。Linux是一个开源、免费的操作系统&#xff0c;其稳定性、安全性、处理多并发能力已经得到业界的认可&#xff0c;目前大多数企业级应用甚至是集群项目都部署运行在linux操作系统之上&#xff0c;很多软件公司考虑到开发成本都首选…

CnOpenData中国核酸检测机构及采样点数据

一、数据简介 2020年1月21日&#xff0c;国家卫健委发布1号公告&#xff0c;将新型冠状病毒感染的肺炎纳入《中华人民共和国传染病防治法》规定的乙类传染病&#xff0c;并采取甲类传染病的预防、控制措施。目前&#xff0c;新型冠状病毒肺炎防控仍处于关键阶段&#xff0c;核酸…

ThinkPHP6 文件上传

内置文件上传使用\think\facade\Filesystem类封装方法 目录 简单上传 public存储文件 文件验证 命名规则 使用sha1 使用MD5 使用date 指定文件名称 自定义命名规则 更多上传设置 总结 简单上传 直接上传&#xff0c;使用默认上传设置 $savename \think\facade\F…

业务平台扩展支持TDengine时序数据库方案

1 场景与架构 1.1业务架构 这里涉及项目隐私&#xff0c;架构图不方便公开。 大致情况就是&#xff1a; 应用层的园区畅行、生态宜居、安全守护是我方要交付的系统。 平台层的物联网感知中台是我方平台。 1.2数据架构 从数据架构看&#xff0c;园区畅行…

第四章 git分支操作

4.1什么是分支 在版本控制过程中&#xff0c;同时推进多个任务&#xff0c;为每个任务&#xff0c;我们就可以创建每个任务的单独 分支。使用分支意味着程序员可以把自己的工作从开发主线上分离开来&#xff0c;开发自己分支的时 候&#xff0c;不会影响主线分支的运行。对于初…