Qt文档阅读笔记-Qt插件DECLARE_INTERFACE & METADATA & INTERFACES官方解析及实例
发布日期:2021-06-30 10:59:01 浏览次数:2 分类:技术文章

本文共 5049 字,大约阅读时间需要 16 分钟。

目录

 


 

官方解析

Q_DECLARE_INTERFACE

此宏用于把标识符与类名接口关联起来。这个标识符是唯一的,举个栗子:

#define BrushInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface"  Q_DECLARE_INTERFACE(BrushInterface, BrushInterface_iid)

这个宏通常在被放到一个类被定后的位置。详细内容查看 Plug & pain。
如果你想把Q_DECLARE_INTERFACE用于命名空间的接口类,要确保Q_DECLARE_INTERACE不在命名空间中,举个栗子:
 

namespace Foo  {      struct MyInterface { ... };  }  Q_DECLARE_INTERFACE(Foo::MyInterface, "org.examples.MyInterface")

 

Q_PLUGIN_METADATA

这个宏被用于声明元数据,这个元数据是被实例化插件的一部分。

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

class MyInstance : public QObject  {      Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDummyPlugin" FILE "mymetadata.json")  };

通过查看 Plug & Paint例子查看细节。
注意,这个宏只能出现在可以被实例化的类中(不能放在抽象类中)。
FILE是可选参数,他指向一个json文件。
这个json文件要包含在构建目录中(为资源文件),不然moc会出错。

 

Q_INTERFACES

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

举个栗子:

class BasicToolsPlugin : public QObject,                           public BrushInterface,                           public ShapeInterface,                           public FilterInterface  {      Q_OBJECT      Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface" FILE "basictools.json")      Q_INTERFACES(BrushInterface ShapeInterface FilterInterface)  public:      ...  };

看 Plug & Paint Basic Tools例子查看细节。

 

博主栗子

这里举一个简单的例子,插件放到文件夹plugin中如下图所示:

运行加载插件的exe程序!

 

插件的界面为:

 

这里涉及2个程序,一个是插件端,一个是读取插件端!

插件端程序结构如下:

这里有一个关键,就是插件端,和读取插件端要统一appinterface.h文件,就和调dll,要使用.h一样的逻辑!

下面给出源码:

Plugin.pro

QT       += core gui widgetsTARGET = PluginTEMPLATE = libCONFIG += plugin#DESTDIR = $$[QT_INSTALL_PLUGINS]/genericDEFINES += IDPLUGIN_LIBRARYDEFINES += QT_DEPRECATED_WARNINGSSOURCES += \    widgetdemo.cppHEADERS += \    widgetdemo.h \    appinterface.h \    secondplugin.hDISTFILES += Plugin.jsonunix {    target.path = /usr/lib    INSTALLS += target}FORMS += \    widgetdemo.ui

appinterface.h

#ifndef APPINTERFACE_H#define APPINTERFACE_H#include 
class AppInterface{public: virtual ~AppInterface(){} virtual QString name() = 0; virtual QWidget *widget() = 0; QString libDir(){ return m_libDir.isEmpty() ? "./" : m_libDir; } void setLibDir(QString libDir){ m_libDir = libDir; }private: QString m_libDir;};QT_BEGIN_NAMESPACE#define Interface_iid "com.IT1995.Interface"Q_DECLARE_INTERFACE(AppInterface, Interface_iid)QT_END_NAMESPACE#endif // APPINTERFACE_H

secondplugin.h

#ifndef SECONDPLUGIN_H#define SECONDPLUGIN_H#include "appinterface.h"#include "widgetdemo.h"class SecondPlugin: public QObject, AppInterface{    Q_OBJECT    Q_PLUGIN_METADATA(IID "com.IT1995.Interface")    Q_INTERFACES(AppInterface)public:    QString name(){ return QStringLiteral("Second模块");}    QWidget *widget(){ return new WidgetDemo(); }};#endif // SECONDPLUGIN_H

widgetdemo.h

#ifndef WIDGETDEMO_H#define WIDGETDEMO_H#include 
namespace Ui {class WidgetDemo;}class WidgetDemo : public QWidget{ Q_OBJECTpublic: explicit WidgetDemo(QWidget *parent = 0); ~WidgetDemo();private: Ui::WidgetDemo *ui;};#endif // WIDGETDEMO_H

widgetdemo.cpp

#include "widgetdemo.h"#include "ui_widgetdemo.h"WidgetDemo::WidgetDemo(QWidget *parent) :    QWidget(parent),    ui(new Ui::WidgetDemo){    ui->setupUi(this);}WidgetDemo::~WidgetDemo(){    delete ui;}

 

读取插件端结构如下:

源码如下:

appinterface.h

#ifndef APPINTERFACE_H#define APPINTERFACE_H#include 
class AppInterface{public: virtual ~AppInterface(){} virtual QString name() = 0; virtual QWidget *widget() = 0; QString libDir(){ return m_libDir.isEmpty() ? "./" : m_libDir; } void setLibDir(QString libDir){ m_libDir = libDir; }private: QString m_libDir;};QT_BEGIN_NAMESPACE#define Interface_iid "com.IT1995.Interface"Q_DECLARE_INTERFACE(AppInterface, Interface_iid)QT_END_NAMESPACE#endif // APPINTERFACE_H

widget.h

#ifndef WIDGET_H#define WIDGET_H#include 
namespace Ui {class Widget;}class Widget : public QWidget{ Q_OBJECTpublic: explicit Widget(QWidget *parent = 0); ~Widget();private: Ui::Widget *ui;};#endif // WIDGET_H

main.cpp

#include "widget.h"#include 
int main(int argc, char *argv[]){ QApplication a(argc, argv); Widget w; w.show(); return a.exec();}

widget.cpp

#include "widget.h"#include "ui_widget.h"#include "appinterface.h"#include 
#include
#include
#include
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this); QList
widgetList; QDir pluginsDir(qApp->applicationDirPath() + "/plugin"); foreach(QString filename, pluginsDir.entryList(QDir::Files)){ QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(filename)); QObject *plugin = pluginLoader.instance(); if(plugin){ AppInterface *app = qobject_cast
(plugin); if(app){ widgetList.append(app); } } } if(widgetList.isEmpty()){ QMessageBox::warning(this, "warning", "load plugin error"); } else{ foreach(AppInterface *w, widgetList){ ui->tabWidget->addTab(w->widget(), w->name()); } }}Widget::~Widget(){ delete ui;}

 

转载地址:https://it1995.blog.csdn.net/article/details/86540402 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Qt文件编码转换工具(一) 项目介绍
下一篇:Qt工作笔记-设置窗体底纹以及控件透明度

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月22日 08时33分40秒