Qt插件开发

2023-11-13

前言

插件是一种遵循一定规范的应用程序接口编写出来的程序,本教程说的插件是用于扩展Qt应用程序的插件,笔者做对创建和使用方法,做下简单的记录

一、Qt插件创建和使用流程

1.定义一个接口集(只有纯虚函数的类),用来与插件交流。
2.用宏Q_DECLARE_INTERFACE()将该接口告诉Qt元对象系统。
3.应用程序中用QPluginLoader来加载插件。
4.用宏qobject_cast()来判断一个插件是否实现了接口。

二、定义接口文件

在QtCreator中,新建头文件

 

 头文件的内容修改如下

#ifndef DEVICEPLUGININTERFACE_H
#define DEVICEPLUGININTERFACE_H

#include <QObject>
#include <QJsonObject>

class DevicePluginInterface
{
public:
    //析构函数
    virtual ~DevicePluginInterface() {}
    //测试设备
    virtual bool testDevice(const QJsonObject &requestJsonObject, QString &errorString) = 0;
    //返回设备信息
    virtual const QJsonObject deviceInfo() = 0;
};

#define DEVICEPLUGININTERFACE_IID "com.xdqd.deviceplugin"
Q_DECLARE_INTERFACE(DevicePluginInterface, DEVICEPLUGININTERFACE_IID)

#endif // DEVICEPLUGININTERFACE_H

读者请自行修改,

注:

1.虚析构函数一定要定义,这有助于确保利用基类的指针访问子类时,可以调用子类的析构函数,以避免内存泄漏

遗憾的是,大多数C++编译器并没有警示信息

2.Q_DECLARE_INTERFACE宏,将类定义为接口

3.DEVICEPLUGININTERFACE_IID 应该是与包名格式类似的唯一字符串,可以根据自己的喜好更改

三、创建插件

使用QtCreator创建共享库工程

 

 

工程文件中添加如下代码

CONFIG += plugin

将已写好的接口文件,加入工程中

 

 修改导出类如下

#ifndef TEST_DEVICE_PLUGIN_H
#define TEST_DEVICE_PLUGIN_H

#include "test_device_plugin_global.h"
#include "deviceplugininterface.h"

class TEST_DEVICE_PLUGIN_EXPORT Test_Device_Plugin: public QObject, public DevicePluginInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "com.xdqd.deviceplugin")
    Q_INTERFACES(DevicePluginInterface)
public:
    Test_Device_Plugin();
    //析构函数
    ~Test_Device_Plugin();
    //测试设备
    bool testDevice(const QJsonObject &requestJsonObject, QString &errorString);
    //返回设备信息
    const QJsonObject deviceInfo();

};

#endif // TEST_DEVICE_PLUGIN_H

1.添加接口类的头文件

2.确保导出类Test_Device_Plugin继承了QObject和DevicePluginInterface

3.添加必要的宏,以便将库识别为插件

Q_OBJECT          Qt宏,以便使用Qt特定的功能
Q_PLUGIN_METADATA(IID "com.xdqd.deviceplugin")         用于添加关于插件的元数据
Q_INTERFACES(DevicePluginInterface)        用于声明插件中实现的接口

实现对应函数的功能后,可以直接编译,生成所需的库文件

四、使用插件

创建测试工程

 

 在工程文件中,添加如下内容

CONFIG += plugin

添加接口文件到工程中

把插件放入指定的目录

main函数修改如下

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug()<< QLibrary::isLibrary("test_device_plugin.dll");
    if(!QLibrary::isLibrary("test_device_plugin.dll"))
    {
        qDebug() << "QLibrary::isLibrary not a library";
        return -1;
    }


    QPluginLoader pluginLoader("E:/workplace/plugin/test_device_plugin.dll");

    qDebug() << "QPluginLoader::isLoaded" << pluginLoader.isLoaded();

    DevicePluginInterface *devicePluginInterface = qobject_cast<DevicePluginInterface*>(pluginLoader.instance());
    if(devicePluginInterface)
    {
        QJsonObject requestJsonObject;
        QString errorString;
        qDebug() << devicePluginInterface->testDevice(requestJsonObject, errorString) << errorString;
        qDebug() << devicePluginInterface->testDevice(requestJsonObject, errorString) << errorString;

        qDebug() << devicePluginInterface->deviceInfo();
        pluginLoader.unload(); // we can unload for now
    }
    else
    {
        qDebug() << "plugin error";
    }

    return a.exec();
}

 1.先使用QLibrary::isLibrary()检查下当前的文件是否是一个库文件

2.使用QPluginLoader载入插件文件

 3.使用qobject_cast<>()将插件内的实例,转换成接口类

4.调用接口类的成员函数

注:笔者测试时发现,QPluginLoader需要使用绝对路径,使用相对路径时报错。

示例源码下载

后记

操作系统不同,插件的文件扩展名也可能不同。如window系统下是.dll,macOS是.dylib,linux系统下是.so,android系统下是so

使用插件时,要确保是使用同一编译器和Qt版本,否则可能出现错误

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

Qt插件开发 的相关文章

  • 通过CMake实现Qt项目

    我正在尝试通过 Cmake 构建并运行非常简单且基本的 Qt 示例 删除 pro 文件 以下是Qt项目的代码 自动生成的Qt项目的目录结构为 Cmake my project name headers mainwindow h source
  • 如何在qt中进行异步文件io?

    我想知道如何在qt中实现异步文件io 这在普通的 qt 中是否可以实现 或者有人需要使用另一个库 例如 libuv 来实现这样的事情 我正在查看 QDataStream 但即使它是一个 流 它也不是非阻塞的 我想一种解决方案是制作一个在内部
  • 具有多个父项的 Qt 树模型

    我想构建一棵树 其中一个元素可以引用另一个元素 我想要构建的树是 像这样的东西 A B C D E F P this is a pointer to C D first child of C E second child of C I fo
  • 获取 QPushButton 在 2D 数组 QPushButton 上的索引

    我有一个二维数组QPushButton 当用户单击按钮时如何获取按钮的索引 例如当用户单击按钮时a 2 3 它会显示 2 3 该示例如下所示 Qt 4 5 使用对象名称 您可以为按钮指定唯一的对象名称 理想情况下 名称应该是有效的 C 标识
  • PyQt - 如何从给定的小部件获取顶级父级?

    给定的小部件如何访问它最旧的父级 即顶级小部件 我需要 showMinimized it 现在我正在使用 self parent parent parent showMinimized 但这似乎不是最好的方法 如果它移动了 我需要手动更改父
  • 无法将 QList 分配给 QString

    我遇到这个错误 Unable to assign QList
  • 打开和关闭附加窗口 (QML)

    目前我有一个通过以下方式打开的窗口 property variant win Button id testButton MouseArea onClicked var component Qt createComponent test qm
  • 如何在 OS X 上的 Qt 应用程序中设置应用程序图标,足以进行分发?

    跟进这个答案 https stackoverflow com a 20918932 368896 to 这个问题 https stackoverflow com questions 20909341 what is the fastest
  • 如何让小部件在上下文菜单出现时接收鼠标释放事件

    在Ubuntu20 04上 当上下文菜单出现时 我无法让小部件接收鼠标释放事件 而Windows可以接收 我的pyqt版本是5 15 2 我考虑过手动发送鼠标释放事件 但我不知道当上下文菜单出现时哪些系统会收到鼠标释放事件 这样做可能会导致
  • 如何在QT上暂停和重新启动Qtimer

    我有 Ubuntu 我正在使用 IDEQT on C 我将暂停和恢复计时器 例如 void Ordonnancer les taches on pushButton clicked connect dataTimer SIGNAL time
  • 清除pyqt中布局中的所有小部件

    有没有办法清除 删除 布局中的所有小部件 self plot layout QtGui QGridLayout self plot layout setGeometry QtCore QRect 200 200 200 200 self r
  • 如何在Qt 5中的paintEvent上使用mouseMoveEvent?

    我是 Qt 和 c 的新手 所以我遇到了一些困难 我正在尝试创建一个小部件 它可以获取 mouseMoveEvent 位置并在鼠标位置的像素图上绘制椭圆 下面你可以看到代码 include myimage h include
  • 如何去除QWizard中的水平线?

    我正在研究一个样式表QWizard我想删除按钮上方的水平线 我尝试递归浏览所有小部件并将其边框设置为无 但似乎没有任何小部件具有此边框 这是我的代码 可以找到完整的可构建示例here https gist github com ardeid
  • QML 中可重用的字体属性[重复]

    这个问题在这里已经有答案了 在 QML 中 我希望能够定义一组字体属性以进行简单的语义重用 例如 代替 Text text This is a header font family Encode Sans weight Font Black
  • 如何在针对 Windows XP 的情况下使用 VS2012 构建 Qt 4/5?

    我正在尝试使用 Visual Studio 2012 构建 Qt 4 8 5 Qt 5 2 1 针对 Windows XP SDK v7 1a 使用 VS2102 编译时 源代码与 SDK v7 1a 存在各种不兼容性 因此无法开箱即用 这
  • 在 Qt 中使用多个不同的流读取同一文件

    使用 Qt 是否可以使用多个流读取文件以同时访问其中的不同数据部分 请注意 Qt 中的流 QTextStream QDataStream 不处理底层设备中的位置 流类只是一个包装器 用于更轻松地解析设备 QFile 实例 内的二进制数据 因
  • Qt中Q_PROPERTY的意义是什么?

    我无法理解 Q PROPERTY 的用法 Q PROPERTY 如何帮助程序具有防御性 它是干什么用的 我看过这个论坛 但确实无法应用 我已经理解了这个例子 但不明白它的用法 这是一个例子 我能从中得到什么 我知道阅读将赋予只读特权 wri
  • 如何将自定义 Qt 类型与 QML 信号一起使用?

    我在 Qt 5 2 qml 应用程序中创建了一个自定义类型 class Setting public QObject Q OBJECT Q PROPERTY QString key READ key WRITE setKey Q PROPE
  • 即使我在单独的线程中运行,QT GUI 也会冻结

    我有一个小型聊天应用程序 其中使用 SQLite 数据库来存储所有对话 我注意到该应用程序随机冻结 然后我必须最小化和最大化它才能使其再次工作 我认为问题可能是 SQLite 选择 插入导致 gui 冻结 我决定尝试将所有 SQLite 方
  • 通过单击内部小部件而不是标题栏来移动窗口

    在 Windows 中 当我创建 QMainWindow 时 我可以通过单击标题栏并拖动它来在屏幕上移动它 在我的应用程序中 我使用隐藏了标题栏setWindowFlags Qt CustomizeWindowHint 我正在尝试使用小部件

随机推荐

  • GitHub使用--上传一个文件

    上传文件到GitHub需要用到两个软件 分别是GitHub TortoiseGit 创建步骤如下 1 选择文件夹 2 右键选择 代码仓库 3 如果上传的文件根目录是这个 就不勾选 反之勾选 4 确认 5 文件右击选择commit 6 填写M
  • 扩展阿里p3c实现自定义代码规范检查

    前段时间fastjson报出了漏洞 只要打开setAutoType特性就会存在风险 自己测试环境的一个项目被揪出来了 虽然改动很小 但就是觉得憋屈 fastjson还是挺好的 想着禁用的话太可惜 用的话又要注意安全 就想着找款工具提示下在用
  • Node.js基础——模块

    文章目录 在Vscode上使用node js运行js代码 法一 终端运行 法二 右键Run Code Vsode设置node代码提示 CommonJS规范 模块化规范 JS标准的缺陷 没有模块化系统带来的影响 CommonJS的模块化规范
  • Flutter运行在Android上卡Running Gradle task ‘assembleDebug...

    Flutter运行在Android上卡Running Gradle task assembleDebug 是因为无法访问官方源 下面进行换源 1 修改配置文件 buildscript repositories google mavenCen
  • 代码静态分析

    1 简介 静态测试包括代码检查 静态结构分析 代码质量度量等 它可以由人工进行 充分发挥人的逻辑思维优势 也可以借助软件工具自动进行 代码检查代码检查包括代码走查 桌面检查 代码审查等 主要检查代码和设计的一致性 代码对标准的遵循 可读性
  • 微信小程序中使用video组件

    文章目录 前情提要 搭建视频服务器 小程序项目 app json pages index index wxml pages index index wxss pages index index js 相关链接 前情提要 小程序里要放置视频
  • 算法:邮局选址问题

    一条直线上有N个居民点 需要建设K个邮局 邮局只能建在居民点上 则所有居民点到最近邮局到最短距离是 动态规划 时间O N N 核心思想 外层循环 邮局数量K 直到包括最大邮局 中层循环 区间 0 R 直到包括整个区间 内层循环 从 0 R
  • 2021-03-20

    Tensorflow 从本地导入数据集 离线使用数据集 1 keras datasets cifar10 load data 进入函数load data j将函数中的path 路径进行修改 dirname cifar 10 batches
  • VM vSphere 导出OVF文件,导入VM Workstation 无法正常引导进入系统

    VM vSphere 导出OVF文件 导入VM Workstation 无法正常引导进入系统的原因有很多种 本次进行修复的原因为 蓝屏错误 终止代码 KMODE EXCEPTION NOT HANDLED 1 首先排查是VM Worksta
  • vscode中使用emmet

    vscode内置emmet功能 可以用在html jsx css sass less等文件上 但是默认没有开启 在setting中添加 emmet triggerExpansionOnTab true 之后 在 html文件里输入div m
  • 本体构建——使用Protege利用Cellfie批量导入excel数据时常见错误及解决方法

    protege利用Cellfie导入数据 https blog csdn net mysky54 article details 108033813 在Tools Create axioms from Excel workbook 中打开文
  • 数字SOC设计之低功耗设计入门(三)——系统与架构级低功耗设计

    前面讲解了使用EDA工具 主要是power compiler 进行功耗分析的流程 这里我们将介绍在数字IC中进行低功耗设计的方法 同时也结合EDA工具 主要是Design Compiler 如何实现 我们的讲解的低功耗设计主要是自顶向下的设
  • JS&Java 交互 报错 JavaException was raised during method Invocation

    如上图所示当JS调用本地方法时报错 原因让人很容易忽略 在与JS交互的方法中不能直接操作View 需要放在主线程操作才能生效 如下代码所示 JavascriptInterface public void setTitle final Str
  • 你真的了解栈溢出么?

    记得之前看过一篇文章说 最好查的bug是语法错误 因为编译器会告诉你 最不好查的bug是栈溢出 因为啥 因为不仅编译器不会告诉你 连你自己有可能都找不到原因出在哪 经过了一段时间的摸索 算是基本搞清楚了栈溢出的原理 写下来以防日后出现问题无
  • js的函数作用域跟块级作用域

    一 js中的作用域 js中除了全局作用域 还有函数作用域 嗯 还有块级作用域 二 函数作用域跟块级作用域的区别 当将代码看成一个IIFE时 全局作用域其实就是一个函数作用域 那么函数作用域跟块级作用域的区别是什么呢 函数作用域 变量在定义的
  • ERROR: cannot launch node of type [map_server/map_server]: map_server

    如上图所示 版本号为 noetic 根据ros版本号 进行安装 sudo apt get install ros noetic map server 将noetic换成你的版本号
  • 枚举的简单例题

    描述 给你n根火柴棍 你可以拼出多少个形如 A B C 的等式 等式中的A B C是用火柴棍拼出的整数 若该数非零 则最高位不能是0 用火柴棍拼数字0 9的拼法如图所示 注意 加号与等号各自需要两根火柴棍 如果A B 则A B C与B A
  • 如何删除文件夹右键菜单多余项

    如何删除文件夹右键菜单多余项 1 所有或大部分文件都有的右键菜单 打开注册表编辑器后 在 HKEY CLASSES ROOT Shellex ContextMenuHandlers 根据名称删除相应的子项 2 文件夹的右键菜单 在注册表中的
  • ST-LINK Utility 烧录 hex、bin 文件——软件下载、驱动安装、使用教程、连接问题解决

    目录 前期准备 ST LINK Utility 下载 ST LINK 驱动安装 ST LINK Utility 使用 连接设备 擦除芯片 烧录 连接问题 no stlink detected 连接设备失败的问题 参考 ST LINK Uti
  • Qt插件开发

    前言 插件是一种遵循一定规范的应用程序接口编写出来的程序 本教程说的插件是用于扩展Qt应用程序的插件 笔者做对创建和使用方法 做下简单的记录 一 Qt插件创建和使用流程 1 定义一个接口集 只有纯虚函数的类 用来与插件交流 2 用宏Q DE