Qt文档阅读笔记-Qt插件DECLARE_INTERFACE & METADATA & INTERFACES官方解析及实例

发布时间 2023-10-22 15:51:42作者: 阳光下的小土豆

转自:https://blog.csdn.net/qq78442761/article/details/86540402

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

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

 

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

1   namespace Foo
2   {
3       struct MyInterface { ... };
4   }
5  
6   Q_DECLARE_INTERFACE(Foo::MyInterface, "org.examples.MyInterface")

 

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

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

 

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

 

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

 1   class BasicToolsPlugin : public QObject,
 2                            public BrushInterface,
 3                            public ShapeInterface,
 4                            public FilterInterface
 5   {
 6       Q_OBJECT
 7       Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface" FILE "basictools.json")
 8       Q_INTERFACES(BrushInterface ShapeInterface FilterInterface)
 9   public:
10       ...
11   };

 

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

 

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

 

 

运行加载插件的exe程序!

 

 

插件的界面为:

 

 

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

插件端程序结构如下:

 

 

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

下面给出源码:

Plugin.pro

 1 QT       += core gui widgets
 2  
 3 TARGET = Plugin
 4 TEMPLATE = lib
 5 CONFIG += plugin
 6  
 7 #DESTDIR = $$[QT_INSTALL_PLUGINS]/generic
 8 DEFINES += IDPLUGIN_LIBRARY
 9  
10  
11 DEFINES += QT_DEPRECATED_WARNINGS
12  
13 SOURCES += \
14     widgetdemo.cpp
15  
16 HEADERS += \
17     widgetdemo.h \
18     appinterface.h \
19     secondplugin.h
20 DISTFILES += Plugin.json
21  
22 unix {
23     target.path = /usr/lib
24     INSTALLS += target
25 }
26  
27 FORMS += \
28     widgetdemo.ui

 

appinterface.h

 1 #ifndef APPINTERFACE_H
 2 #define APPINTERFACE_H
 3  
 4 #include <QObject>
 5  
 6 class AppInterface{
 7 public:
 8     virtual ~AppInterface(){}
 9     virtual QString name() = 0;
10     virtual QWidget *widget() = 0;
11  
12     QString libDir(){
13         return m_libDir.isEmpty() ? "./" : m_libDir;
14     }
15  
16     void setLibDir(QString libDir){
17         m_libDir = libDir;
18     }
19  
20 private:
21     QString m_libDir;
22  
23 };
24  
25 QT_BEGIN_NAMESPACE
26  
27 #define Interface_iid "com.IT1995.Interface"
28  
29 Q_DECLARE_INTERFACE(AppInterface, Interface_iid)
30  
31 QT_END_NAMESPACE
32  
33 #endif // APPINTERFACE_H

 

secondplugin.h

 1 #ifndef SECONDPLUGIN_H
 2 #define SECONDPLUGIN_H
 3  
 4 #include "appinterface.h"
 5 #include "widgetdemo.h"
 6  
 7 class SecondPlugin: public QObject, AppInterface{
 8     Q_OBJECT
 9     Q_PLUGIN_METADATA(IID "com.IT1995.Interface")
10     Q_INTERFACES(AppInterface)
11 public:
12     QString name(){ return QStringLiteral("Second模块");}
13     QWidget *widget(){ return new WidgetDemo(); }
14 };
15  
16 #endif // SECONDPLUGIN_H

 

widgetdemo.h

 1 #ifndef WIDGETDEMO_H
 2 #define WIDGETDEMO_H
 3  
 4 #include <QWidget>
 5  
 6 namespace Ui {
 7 class WidgetDemo;
 8 }
 9  
10 class WidgetDemo : public QWidget
11 {
12     Q_OBJECT
13  
14 public:
15     explicit WidgetDemo(QWidget *parent = 0);
16     ~WidgetDemo();
17  
18 private:
19     Ui::WidgetDemo *ui;
20 };
21  
22 #endif // WIDGETDEMO_H

 

widgetdemo.cpp

 1 #include "widgetdemo.h"
 2 #include "ui_widgetdemo.h"
 3  
 4 WidgetDemo::WidgetDemo(QWidget *parent) :
 5     QWidget(parent),
 6     ui(new Ui::WidgetDemo)
 7 {
 8     ui->setupUi(this);
 9 }
10  
11 WidgetDemo::~WidgetDemo()
12 {
13     delete ui;
14 }

 

读取插件端结构如下:

 

 

源码如下:

appinterface.h

 1 #ifndef APPINTERFACE_H
 2 #define APPINTERFACE_H
 3  
 4 #include <QObject>
 5  
 6 class AppInterface{
 7 public:
 8     virtual ~AppInterface(){}
 9     virtual QString name() = 0;
10     virtual QWidget *widget() = 0;
11  
12     QString libDir(){
13         return m_libDir.isEmpty() ? "./" : m_libDir;
14     }
15  
16     void setLibDir(QString libDir){
17         m_libDir = libDir;
18     }
19  
20 private:
21     QString m_libDir;
22  
23 };
24  
25 QT_BEGIN_NAMESPACE
26  
27 #define Interface_iid "com.IT1995.Interface"
28  
29 Q_DECLARE_INTERFACE(AppInterface, Interface_iid)
30  
31 QT_END_NAMESPACE
32  
33 #endif // APPINTERFACE_H

 

widget.h

 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3  
 4 #include <QWidget>
 5  
 6 namespace Ui {
 7 class Widget;
 8 }
 9  
10 class Widget : public QWidget
11 {
12     Q_OBJECT
13  
14 public:
15     explicit Widget(QWidget *parent = 0);
16     ~Widget();
17  
18 private:
19     Ui::Widget *ui;
20 };
21  
22 #endif // WIDGET_H

 

main.cpp

 1 #include "widget.h"
 2 #include <QApplication>
 3  
 4 int main(int argc, char *argv[])
 5 {
 6     QApplication a(argc, argv);
 7     Widget w;
 8     w.show();
 9  
10     return a.exec();
11 }

 

widget.cpp

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include "appinterface.h"
 4 #include <QDir>
 5 #include <QPluginLoader>
 6 #include <QMessageBox>
 7 #include <QDebug>
 8  
 9 Widget::Widget(QWidget *parent) :
10     QWidget(parent),
11     ui(new Ui::Widget)
12 {
13     ui->setupUi(this);
14  
15     QList<AppInterface*> widgetList;
16  
17     QDir pluginsDir(qApp->applicationDirPath() + "/plugin");
18  
19     foreach(QString filename, pluginsDir.entryList(QDir::Files)){
20  
21         QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(filename));
22         QObject *plugin = pluginLoader.instance();
23  
24         if(plugin){
25             
26             AppInterface *app = qobject_cast<AppInterface*>(plugin);
27             if(app){
28  
29                 widgetList.append(app);
30             }
31         }
32     }
33  
34     if(widgetList.isEmpty()){
35         
36         QMessageBox::warning(this, "warning", "load plugin error");
37  
38     }
39     else{
40         foreach(AppInterface *w, widgetList){
41  
42             ui->tabWidget->addTab(w->widget(), w->name());
43         }
44     }
45 }
46  
47 Widget::~Widget()
48 {
49     delete ui;
50 }

 

————————————————
版权声明:本文为CSDN博主「IT1995」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq78442761/article/details/86540402