当前位置: 首页 > news >正文

一、插件开发入门【Qt环境-mingw6.5.3-qmake版】-封装dll调用

1.先创建一个名为mainProject的主项目,并进行简单的ui布局

image.png
image.png
image.png
image.png
image.png

2.使用C++ Library库创建动态库项目作为主项目的子插件

image.png

2.1 Qt模块选择为Widgets

image.png

2.2 环境配置和主项目要一致

image.png

3.给插件添加qt界面设计类

image.png
image.png

image.png
image.png

4.给subPlugin插件添加一个名为PluginInterface.h的头文件

image.png
image.png

#ifndef PLUGININTERFACE_H
#define PLUGININTERFACE_H#include <QWidget>#define PluginInterfaceIID "com.szweebon.PluginInterface/1.0.0" // 定义一个插件接口的唯一标识符(IID),用于标识插件的接口版本class PluginInterface{ // 这是一个纯虚基类(接口),用于定义插件接口的标准。
public:virtual ~PluginInterface() = default; // 虚析构函数,确保派生类在销毁时能够正确释放资源virtual QWidget *getWidget() = 0;   // 该函数用于返回一个 QWidget 指针,表示插件提供的界面部件
};Q_DECLARE_INTERFACE(PluginInterface, PluginInterfaceIID) // 确保接口类和它的 IID 在 Qt 元对象系统中注册
#endif // PLUGININTERFACE_H

5.编辑subplugin.h和subplugin.cpp代码

#ifndef SUBPLUGIN_H
#define SUBPLUGIN_H
#include "PluginInterface.h"
#include "subPlugin_global.h"class SUBPLUGIN_EXPORT SubPlugin: public QObject, public PluginInterface
{Q_OBJECTQ_PLUGIN_METADATA(IID PluginInterfaceIID)//PluginInterfaceIID就是IIDQ_INTERFACES(PluginInterface)
public:SubPlugin();~SubPlugin();QWidget *getWidget();
private:QWidget *mGenWidget;
};#endif // SUBPLUGIN_H
#include "subplugin.h"
#include "form.h"
SubPlugin::SubPlugin() {mGenWidget = Q_NULLPTR;
}SubPlugin::~SubPlugin() {if(mGenWidget){mGenWidget->deleteLater();}
}
QWidget *SubPlugin::getWidget()
{if(!mGenWidget){mGenWidget = new Form;}return mGenWidget;
}

6.去掉mainProject项目和subPlugin项目的的影子编译

image.png
image.png

7.将插件subPlugin项目的PluginInterface.h赋值一份到mianProject项目中,并添加到主项目录

image.png
image.png
image.png

8.把subPlugin项目生成的dll文件复制一份到mianProject主项目

这个运行动态库项目没有exe是很正常的。反正我的没有,有dll就行
image.png
image.png

image.png

9.编写主程序代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>#include <QPluginLoader>//插件加载类QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_clicked();private:Ui::MainWindow *ui;QPluginLoader  loader;bool isPluginLoaded;         // 标志插件是否已加载void removeTabWithTitle(const QString &title);
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "PluginInterface.h"
#include <QDir>
#include <QMessageBox>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow), isPluginLoaded(false)  // 新增标志以跟踪插件是否已加载
{ui->setupUi(this);// 初始化按钮文本ui->pushButton->setText("加载插件");
}MainWindow::~MainWindow()
{// 在销毁窗口时,检查并卸载已加载的插件if (isPluginLoaded) {loader.unload();}delete ui;
}void MainWindow::on_pushButton_clicked()
{if (isPluginLoaded) {// 如果插件已经加载,执行卸载操作loader.unload();removeTabWithTitle("插件标签");  // 清除具有特定标题的标签页isPluginLoaded = false;  // 更新插件加载标志ui->pushButton->setText("加载插件");  // 更新按钮文本qDebug("插件已卸载");} else {// 插件未加载时,进行加载操作QDir dir("D:/EmbeddedDevelopment/Qt/Plugins/mainProject/debug");// 如果需要使用应用程序的运行目录,可以启用以下代码// QDir dir(qApp->applicationDirPath());qDebug("目录1: %s", dir.path().toUtf8().constData());  // 输出目录路径// 设置插件文件路径并准备加载插件loader.setFileName(dir.filePath("subPlugin.dll"));qDebug("目录2: %s", dir.filePath("subPlugin.dll").toUtf8().constData());  // 输出插件文件路径// 尝试加载插件if (!loader.load()) {qDebug("Failed to load loader");QMessageBox::critical(this, "错误", loader.errorString());  // 显示错误信息return;}// 创建插件实例QObject *plugin = loader.instance();if (!plugin) {  // 如果插件实例为空,输出错误信息并退出qDebug("loader.instance() is null");return;}qDebug("插件实例创建成功");// 将插件实例转换为 PluginInterface 类型PluginInterface *pi = qobject_cast<PluginInterface *>(plugin);if (pi) {  // 如果转换成功,获取插件的 QWidget 并添加到 TabWidget 中QWidget *w = pi->getWidget();if (w) {ui->tabWidget->addTab(w, "插件标签");  // 添加插件的 QWidget 为新标签页qDebug("插件标签添加成功");isPluginLoaded = true;  // 更新插件加载标志ui->pushButton->setText("卸载插件");  // 更新按钮文本} else {qDebug("插件未返回有效的 QWidget");}} else {qDebug("插件转换失败,pi is NULL");}}
}void MainWindow::removeTabWithTitle(const QString &title)
{int count = ui->tabWidget->count();for (int i = 0; i < count; ++i) {if (ui->tabWidget->tabText(i) == title) {ui->tabWidget->removeTab(i);return;  // 一旦找到并移除目标标签页后退出}}
}

10.运行结果

可以添加卸载插件界面,其实添加的是一个不能自己独立运行的封装好的动态库界面,而且项目直接没有层级,故我不建议采纳这种方法
image.png


http://www.mrgr.cn/news/8046.html

相关文章:

  • 老师怎样分班更便捷?
  • 排查Maven问题的步骤
  • 致远OA OCR票据识别组件
  • Vue路由—进阶篇
  • [数据集][目标检测]夜间老鼠检测数据集VOC+YOLO格式316张1类别+视频文件1个
  • 牛客,笔试小题
  • 17 深入理解 C 语言 main 函数:返回值意义、命令行参数接收、跨环境差异及CMD乱码解决
  • QEMU运行ARM Linux内核
  • Ubuntu22.04下安装LDAP
  • 【计算机组成原理】三、存储系统:1.存储器的分类、层次化结构、性能指标、基本组成(半导体、存储芯片基本原理)
  • Flutter【02】mobx原理
  • dbeaver数据库工具配置连接openGauss5.0
  • centos7安装Kafka单节点环境部署一-ZooKeeper安装与配置
  • matlab 计算矩阵元素的标准差
  • CSS文字方向控制属性text-orientation
  • 内存管理篇-06Per-CPU页帧缓存
  • OD C卷 - Wonderland游乐园
  • 阵列信号处理2_阵列信号最优处理常用准则(CSDN_20240825)
  • 大话C语言:第46篇 C语言项目工程化之Makefile详解
  • 编程路上的“迷宫逃脱”:从Bug堆到算法之巅的奇妙之旅