Qt文档阅读笔记-Qt插件DECLARE_INTERFACE & METADATA & INTERFACES官方解析及实例
转自: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