Qt - 插件化编程 & 插件框架
Qt插件机制(插件化编程)
1、通过插件扩展应用程序功能
A、定义一个接口集(只有纯虚函数的类),用来与插件交流。
B、用宏Q_DECLARE_INTERFACE()将该接口告诉Qt元对象系统。
C、应用程序中用QPluginLoader来加载插件。
D、用宏qobject_cast()来判断一个插件是否实现了接口。
2、创建插件
A、声明插件类,插件类继承自QObject和插件实现的接口。
B、用宏Q_INTERFACES()将插件接口告诉Qt元对象系统。(注意Qt版本)
C、用宏Q_EXPORT_PLUGIN2()导出插件类。(注意Qt版本)
D、用适当的.pro文件构建插件。
注:在加载插件前,QCoreApplication对象必须被初始化。
Qt插件类创建(插件化编程)
////--------------------------------------------------------------------------------------step 1 定义接口类 class RegExpInterface { public: virtual ~RegExpInterface() {} virtual QString regexp(const QString &message) = 0; }; ////--------------------------------------------------------------------------------------step 2 声明是接口类(接口类中) // 使用 Q_DECLARE_INTERFACE 宏,是为了让Qt元对象系统知道该接口,这样以来,在运行时便可以识别实现接口的插件。 // Q_DECLARE_INTERFACE(接口类名, 接口标识),第二个参数(RegExpInterface_iid)是一个标识接口的字符串,必须唯一。 #define RegExpInterface_iid "org.qter.Examples.myplugin.RegExpInterface" Q_DECLARE_INTERFACE(RegExpInterface,RegExpInterface_iid ) #endif // REGEXPINTERFACE_H ////--------------------------------------------------------------------------------------step 3 实现接口 class REGEXPLUGINSHARED_EXPORT RegexPlugin : public QObject,RegExpInterface { Q_OBJECT //Q_PLUGIN_METADATA宏用于描述插件元数据,第一个参数为插件的 IID,与接口定义的IID相同 //第二个参数FILE是可选的,指定一个本地json文件,该文件中描述插件的相关数据信息 Q_PLUGIN_METADATA(IID RegExpInterface_iid FILE "regexplugindata.json") //Q_INTERFACES 宏用于告诉 Qt 该类实现的接口。 Q_INTERFACES(RegExpInterface) public: RegexPlugin(); // RegExpInterface interface public: QString regexp(const QString &message); }; ////---------------------------------------------------------------------------------------step 4 使用接口 // 进入插件目录 QDir pluginsDir(qApp->applicationDirPath()); pluginsDir.cd("bin"); // 遍历插件目录 foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName)); QObject *plugin = pluginLoader.instance(); if (plugin) { //取回json文件的内容 QJsonObject w = pluginLoader.metaData().value("MetaData").toObject(); qDebug()<<w; regexpInterface = qobject_cast<RegExpInterface *>(plugin); if (regexpInterface) return true; } }
自己写的插件框架:定义消息传递基类+使用(独立)
//-------------------------------------------------------------------BlzBaseMsgData.h /** * 继承和多态:统一消息传递类型(暂时没有使用) * 单头文件:定义消息传递基类(只存放所有模块的消息传递基础数据,非详细数据) */ #pragma once #include <QObject> #include <QDateTime> /******************消息 相关全局变量******************/ const int MSG_FALSE = -1; //失败 const int MSG_TRUE = 0; //成功 //数据类的基类:消息中的数据 class BlzBaseData { public: virtual ~BlzBaseData() = default; }; //消息类(用于信号槽):统一函数参数 struct BlzMessage { //QString from; //消息来源地 //QString dest; //消息目的地 //QString msg; //消息简述 int nId; //消息id int nResult = MSG_TRUE; //执行结果 std::shared_ptr<BlzBaseData> pBaseData = nullptr; //消息数据 }; Q_DECLARE_METATYPE(BlzMessage); //确保类型可以通过信号槽传递 /******************模块类的基类******************/ //模块类的基类:统一模块对外发送消息接口和接收消息接口 class BlzInterface: public QObject { Q_OBJECT public: BlzInterface(QObject* parent): QObject(parent) {} signals: void signalSendMesage(BlzMessage& blzMessage); public slots: virtual void slotRecvMessage(BlzMessage& blzMessage) {} }; /******************宏函数:防止每个模块中消息id重复******************/ #define MESSAGE_ID_GENERATE(a, b) ( ((a) << (b)) % UINT_MAX ) #define MESSAGE_ID_BLZ10 0x10 //Blz10 #define MESSAGE_ID_BLZ11 0x11 //Blz11 #define MESSAGE_ID_BLZ12 0x12 //Blz12 #define MESSAGE_ID_BLZRTC 0x13 //BlzRTC //-------------------------------------------------------------------end //-------------------------------------------------------------------BlzRTCMsgData.h #pragma once /** * 单一个头文件:定义消息传递类型(只存放该模块的消息传递详细数据) */ #include "Common/BlzBaseMsgData.h" /******************消息 id******************/ const unsigned int BLZRTC_SET_DATETIME = MESSAGE_ID_GENERATE(MESSAGE_ID_BLZRTC, 0x01); /******************消息 class******************/ class BlzRTCData : public BlzBaseData { public: BlzRTCData() {} ~BlzRTCData() override = default; QDateTime m_dateTime; }; //-------------------------------------------------------------------end //-------------------------------------------------------------------BlzRTC.h #pragma once #include <QObject> #include "Common/BlzBaseMsgData.h" #include "BlzRTCMsgData.h" #include "hs_rtc.h" class BlzRTC : public BlzInterface { Q_OBJECT public: BlzRTC(BlzInterface* parent = nullptr); ~BlzRTC() override = default; bool setDateTime(QDateTime& dt); private: //设置系统日期时间 void setDateTime(const BlzMessage& blzMessage); public slots: void slotRecvMessage(BlzMessage& blzMessage) override; }; //-------------------------------------------------------------------end //-------------------------------------------------------------------BlzRTC.cpp #include "BlzRTC.h" BlzRTC::BlzRTC(BlzInterface* parent) : BlzInterface(parent) {} bool BlzRTC::setDateTime(QDateTime& dt) { return rtc_set_DateTime(dt); } void BlzRTC::setDateTime(const BlzMessage& blzMessage) { if (blzMessage.pBaseData == nullptr) { return; } std::shared_ptr<BlzRTCData> pData = std::dynamic_pointer_cast<BlzRTCData>(blzMessage.pBaseData); } void BlzRTC::slotRecvMessage(BlzMessage& blzMessage) { switch (blzMessage.nId) { case BLZRTC_SET_DATETIME: setDateTime(blzMessage); break; default: break; } } //-------------------------------------------------------------------end
插件框架项目目录(独立)
1、基础接口类(`PluginBase`)
- **职责**:定义插件必须实现的接口,作为所有插件的基类。
- **纯虚函数**:
- `init()`:插件初始化(如资源加载)。
- `exec()`:插件核心功能执行。
- `destroy()`:插件销毁(如释放资源)。
- `getPluginInfo()`:获取插件元信息(名称、版本等)。
2、插件管理器类(`PluginManager`)
- **职责**:管理插件的加载、卸载、调用和生命周期。
- **核心功能**:
- 动态加载插件库(`loadPlugin()`)。
- 枚举已加载插件(`listPlugins()`)。
- 执行指定插件(`executePlugin()`)。
- 统一管理插件的初始化和销毁。
3、工具类(`PlatformUtils`、`Logger`)
- **`PlatformUtils`**:封装动态库加载的平台差异(Windows 的 `LoadLibrary`/Linux 的 `dlopen`)。
- **`Logger`**:提供日志输出功能,用于框架调试和插件监控。
4、示例插件实现
5、使用流程
**编译插件**:将示例插件编译为动态库(Windows 生成 `.dll`,Linux 生成 `.so`)。
**加载插件**:通过 `PluginManager::loadPlugin("path/to/plugin.so")` 加载。
**执行插件**:调用 `executePlugin` 触发插件功能。
**卸载插件**:程序退出前调用 `unloadAllPlugins` 释放资源。
6、扩展建议
**插件通信**:通过消息机制(如观察者模式)实现插件与主程序或插件间通信。
**安全校验**:添加插件签名校验,防止恶意代码注入。
**热更新**:支持运行时重新加载插件,无需重启主程序。
**依赖管理**:为插件添加依赖声明,由管理器自动解析加载顺序。
plugin_framework //框架基于动态链接库(dll/so)实现插件加载 ----include/ //头文件目录 --------plugin_base.h //插件基类与接口定义 --------plugin_manager.h //插件管理器类 --------utils/ //工具头文件 ------------platform.h //平台相关API(动态库加载) ------------logger.h //日志工具 ----src/ //源文件目录 --------plugin_base.cpp --------plugin_manager.cpp --------utils/ ------------platform.cpp ------------logger.cpp ----plugins/ //插件示例目录 --------example_plugin/ //示例插件 ------------example_plugin.h //插件头文件(继承基类) ------------example_plugin.cpp //插件源文件 --------cmakelist.txt //插件编译配置(生成动态库) ----test/ //测试目录 --------test_main.cpp //框架测试代码 ----cmakelist.txt //框架编译配置 ----readme.txt
end
浙公网安备 33010602011771号