Qt--QPlugin插件
写在前面
Qt–动态链接库一文中提到,动态方式加载dll只能加载 extern "C“ 的导出函数,而无法加载类,因此可以使用Qt提供的插件来实现导出类的动态加载。
QPlugin是Qt插件框架的一部分,是一种轻量级的插件系统,用于在QT应用程序中动态加载和卸载功能模块,QPluginLoader类提供了对Qt插件的访问。
开发环境:
Qt5.15.2
Qt Creator10.0.2
自定义插件步骤
自定义插件时,要先创建一个接口,作为插件类的基类。因为插件存储在一个dll中,因此可以动态的加载。
创建一个插件包含以下几步:
①定义一个接口类(只有纯虚函数的抽象类)
②使用Q_DECLARE_INTERFACE()宏在Qt的元对象系统中注册该接口
③再定义一个插件类,必须继承自QObject类和上面创建的接口类,且需先继承QObject
④在插件类中使用Q_INTERFACE()宏在Qt的元对象系统中注册该接口
⑤使用Q_PLUGIN_METADATa()宏导出该插件
⑥使用合适的.pro文件构建该插件
这里和之前的dll的创建和使用一样,同样以两个项目进行,一个插件项目,一个使用插件项目。
创建插件
打开Qt Creator,新建空项目,Empty qmake Project。

命名为:MyPlugin

套件配置:

新建一个MyPluginInterface 接口类:

在MyPluginInterface.h中添加以下内容:
//myplugininterface.h
#ifndef MYPLUGININTERFACE_H
#define MYPLUGININTERFACE_H#define MYPLUGININTERFACE_IID "org.examples.myplugin.interface”class MyPluginInterface
{
public:virtual ~MyPluginInterface() {} //这里需内敛实现virtual void printFromPlugin() = 0; //声明为纯虚函数};Q_DECLARE_INTERFACE(MyPluginInterface, MYPLUGININTERFACE_IID)#endif // MYPLUGININTERFACE_H
再创建插件类,继承自QObject:


添加对QMyPluginInterface的继承,元对象的接口注册和导出:
//myplugin.h
#ifndef MYPLUGIN_H
#define MYPLUGIN_H#include <QObject>
#include "MyPluginInterface.h"class MyPlugin : public QObject, MyPluginInterface
{Q_OBJECTQ_PLUGIN_METADATA(IID MYPLUGININTERFACE_IID)Q_INTERFACES(MyPluginInterface)public:explicit MyPlugin(QObject *parent = nullptr);void printFromPlugin(); //实现继承自基类的纯虚函数signals:};#endif // MYPLUGIN_H
//myplugin.cpp
#include "myplugin.h"
#include <QDebug>MyPlugin::MyPlugin(QObject *parent): QObject{parent}
{}void MyPlugin::printFromPlugin()
{qDebug() << "Print From Plugin";
}
最后修改.pro文件,构建项目:
//MyPlugin.pro
TEMPLATE = lib #表明该项目要构建库
CONFIG += plugin #告知qmake要创建一个插件HEADERS += \MyPluginInterface.h \myplugin.hSOURCES += \myplugin.cpp
构建会提示MyPluginInterface.h中有错误:D:\QtApplication\MyPlugin\MyPlugin\MyPluginInterface.h:15: error: Parameter type ‘MyPluginInterface’ is an abstract class

这里将MyPluginInterface.h从项目中移除,注意不要删除!

再重新构建生成即可:

可以在输出目录下看到dll:

然后提供:
①MyPluginInterface.h
②MyPlugin.dll
给其他项目使用即可。
使用插件
这里新建一个Qt控制台应用程序,来加载上面的插件并使用:


构建套件:

将MyPluginInterface.h拷贝到MyPluginTest.pro目录的include文件夹中,将MyPlugin.dll放到MyPluginTest项目的输出目录下:


在MyPluginTest.pro中添加包含目录:

在main.cpp中加载使用MyPlugin:
//main.cpp
#include <QCoreApplication>#include <QDebug>
#include <QPluginLoader>
#include "MyPluginInterface.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);//QPluginLoader loader("D:/QtApplication/MyPluginTest/build-MyPluginTest-Desktop_Qt_5_15_2_MSVC2019_64bit-Release/MyPlugin.dll");QPluginLoader loader("../MyPlugin.dll");QObject* instance = loader.instance();if (instance){MyPluginInterface* plugin = qobject_cast<MyPluginInterface*>(instance);if (plugin){plugin->printFromPlugin();}}else{qDebug() << "Instance is null";return 0;}return a.exec();
}
输出结果如下:

总结
使用QPluginLoader可动态加载dll,通过QPluginLoader::instance()得到插件接口类的实例,再通过多态调用对应插件类的接口实现,以此来弥补QLibrary不能动态加载使用导出类的缺陷。
后续扩展其他插件时,需添加抽象的插件接口类(MyPluginInterface)及其对应的插件类(MyPlugin)实现。
相关文章:
Qt--QPlugin插件
写在前面 Qt–动态链接库一文中提到,动态方式加载dll只能加载 extern "C“ 的导出函数,而无法加载类,因此可以使用Qt提供的插件来实现导出类的动态加载。 QPlugin是Qt插件框架的一部分,是一种轻量级的插件系统,…...
公会发展计划 (GAP) 第 4 季:塑造 YGG 的成就版图
基于前三个赛季所取得的成果,Yield Guild Games(YGG)自豪地宣布推出 公会发展计划(GAP)第 4 季。公会最近的一些精英成员将在本季加入公会,公会成员将在全新的任务中磨练自己的技能,建立自己在 …...
ExpressJS教程_编程入门自学教程_菜鸟教程-免费教程分享
教程简介 Express是基于Node.js平台,快速、开放、极简的Web开发框架;通俗的理解:Express的作用和Node.js内置的http模块类似,是专门用来创建Web服务器的;Express的本质:就是一个npm上的第三方包,提供了快速创建Web服务器的便捷方法。ExpressJS是一个Web…...
时序预测 | MATLAB实现BO-BiLSTM贝叶斯优化双向长短期记忆神经网络时间序列预测
时序预测 | MATLAB实现BO-BiLSTM贝叶斯优化双向长短期记忆神经网络时间序列预测 目录 时序预测 | MATLAB实现BO-BiLSTM贝叶斯优化双向长短期记忆神经网络时间序列预测效果一览基本介绍模型搭建程序设计参考资料 效果一览 基本介绍 MATLAB实现BO-BiLSTM贝叶斯优化双向长短期记忆…...
HIVE优化之不需要参数优化
#1.数据倾斜 什么是数据倾斜? 一部分数据多 一部分数据少 造成的结果: MR运行过慢 主要是shuffle和reduce过程慢 分组聚合导致数据倾斜 Hive未优化的分组聚合 方法1:在MAP端直接聚合(分组聚合优化),减少…...
前端 select 标签如何创建下拉菜单?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 代码示例⭐ 代码讲解⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚踏…...
基于 eclipse-temurin 构建国内时区,地区,语言的docker镜像
基于 eclipse-temurin 构建国内时区,地区,语言的镜像 使用场景自定Dockerfile构建自己的基础镜像构建本地镜像推送远程仓库 使用场景 在给应用构建自定义镜像时,往往需要在每次构建时去调整时区,地区这些东西;每次构建…...
RunnerGo配置场景时接口模式该怎么选
在进行性能测试时,测试场景的正确配置非常关键。首先,需要根据业务场景和需求,设计出合理的测试场景,再利用相应的工具进行配置,实现自动化的性能测试。 在JMeter中,用户需要自己组织测试场景,…...
系统分享UIActivity
iOS自带的分享控件可以完成绝大部分的分享需求。 它可以不需要集成微信、QQ等第三方SDK就可以实现分享(需要在弹出视图里面点击更多打开开关)到微信好友、朋友圈等,功能很强大,也很方便。 一、系统分享两个步骤 UIActivity配置分享的内容和…...
常用抓包工具
Fiddler Fiddler 是一个很好用的抓包工具,可以用于抓取http/https的数据包,常用于Windows系统的抓包,它有个优势就是免费 Charles Charles是由JAVA开发的,可以运行在window Linux MacOS,但它是收费的,和…...
自然语言处理学习笔记(五)————切分算法
目录 1.切分算法 2.完全切分 3.正向最长匹配 4.逆向最长匹配 5.双向最长匹配 6.速度评测 1.切分算法 词典确定后,句子可能含有很多词典中的词语,他们有可能互相重叠,如何切分需要一些规则。常用规则为:正向匹配算法、逆向匹…...
SQL-方法论
写SQL时可以考虑的手段: 行转列 先分为多个临时表,然后JOIN到一起 select uid,t1.name YuWen,t2.name ShuXue from (select uid,namefrom tableAwhere naem 语文) t1join (select uid,namefrom tableAwhere naem 数学) t2on t1.uid t2.uid; 用sum(if…...
[Python从零到壹] 六十八.图像识别及经典案例篇之图像特效(毛玻璃、浮雕、油漆和模糊特效变换)
八月太忙,还是写一篇吧! 欢迎大家来到“Python从零到壹”,在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界。所有文章都将结合案例、代码和作者的经验讲解,真心想把自己近十年的编程经验分享给大家,希望对您有所帮助,文章中不足…...
undefined与null的区别
null 表示一个对象被定义了,值为“空值” undefined 表示不存在这个值 1.undefined typeof undefined //"undefined" undefined 是一个表示"无"的原始值或者说表示"缺少值",就是此处应该有一个值,但还没有…...
Unity之获取用户地理位置
1.直接利用三方API获取: 1.1 利用bilibili的api 【未知稳定性】 public void Awake() {StartCoroutine(GetLocationInfoNew());}/// <summary>/// 利用bilibili的接口通过ip直接获取城市信息/// </summary>IEnumerator GetLocationInfoNew() {//UnityWebRequest …...
TC3XX - MCAL知识点(二十):CAN MCAL配置及代码实战(CAN/CANFD/extenen CAN)
目录 1、概述 2、MCAL配置 2.1、实验目标 2.2、CAN配置(包含CAN与CANFD) 2.2.1、CanGeneral...
QT生成Debug和Release发布版后,运行exe缺少dll问题
在QT Creator生成debug和release的exe执行文件后,运行时,报错缺少*.dll.解决办法1: 在系统环境变量中添加D:\Qt\Qt5.13.2\Tools\mingw730_64\bin后,即可运行。 当使用此方法时,将exe拷贝到其他电脑中运行时,…...
企业进销存管理流程有哪些? 附进销存管理系统
阅读本文,您可以了解:1、进销存的定义;2、进销存的流程 首先,在了解进销存流程之前,我们必须厘清一个问题? 什么是进销存? 进销存是一个企业管理中常用的术语,是指企业在经营过程中…...
RPC原理与Go RPC详解
文章目录 RPC原理与Go RPC什么是RPC本地调用RPC调用HTTP调用RESTful API net/rpc基础RPC示例基于TCP协议的RPC使用JSON协议的RPCPython调用RPC RPC原理 RPC原理与Go RPC 什么是RPC RPC(Remote Procedure Call),即远程过程调用。它允许像调用…...
JavaScript:异步编程的发展
在JavaScript编程中,异步编程是处理耗时操作的关键技术,它允许程序在等待某些操作完成时继续执行其他任务,提高了程序的性能和响应性。随着技术的发展,JavaScript的异步编程模型也在不断演进,从最初的回调函数到现在的…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
