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

目录

 

官方解析

Q_DECLARE_INTERFACE

Q_PLUGIN_METADATA

Q_INTERFACES

博主栗子


 

官方解析

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中如下图所示:

Qt文档阅读笔记-Qt插件DECLARE_INTERFACE & METADATA & INTERFACES官方解析及实例_第1张图片

运行加载插件的exe程序!

Qt文档阅读笔记-Qt插件DECLARE_INTERFACE & METADATA & INTERFACES官方解析及实例_第2张图片

 

插件的界面为:

Qt文档阅读笔记-Qt插件DECLARE_INTERFACE & METADATA & INTERFACES官方解析及实例_第3张图片

 

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

插件端程序结构如下:

Qt文档阅读笔记-Qt插件DECLARE_INTERFACE & METADATA & INTERFACES官方解析及实例_第4张图片

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

下面给出源码:

Plugin.pro

QT       += core gui widgets

TARGET = Plugin
TEMPLATE = lib
CONFIG += plugin

#DESTDIR = $$[QT_INSTALL_PLUGINS]/generic
DEFINES += IDPLUGIN_LIBRARY


DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
    widgetdemo.cpp

HEADERS += \
    widgetdemo.h \
    appinterface.h \
    secondplugin.h
DISTFILES += Plugin.json

unix {
    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_OBJECT

public:
    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;
}

 

读取插件端结构如下:

Qt文档阅读笔记-Qt插件DECLARE_INTERFACE & METADATA & INTERFACES官方解析及实例_第5张图片

源码如下:

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_OBJECT

public:
    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;
}

 

你可能感兴趣的:(C/C++,Qt,文档阅读笔记)