Qt Advanced - Qt Plugin Development

Qt Advanced - Qt Plugin Development

1. Qt plugin mechanism

1. Introduction to Qt plugins

A plug-in is a program written in accordance with a certain standard application program interface, and is positioned to develop programs that implement functions that the application software platform does not have.

2. Qt plugin API

Qt provides two APIs for creating plugins: one is a high-level API, which is used to extend the functions of Qt itself, such as custom database drivers, image formats, text encoding, custom styles, etc.; the other is a low-level API, Used to extend Qt applications.

3. Extend application functionality through plugins

A. Define an interface set (only classes with pure virtual functions) to communicate with plug-ins.
B. Use the macro Q_DECLARE_INTERFACE() to tell the Qt meta-object system about the interface.
C. Use QPluginLoader to load plug-ins in the application.
D. Use the macro qobject_cast() to judge whether a plug-in implements the interface.

4. Create a plugin

The steps for creating a plug-in are as follows:
A. Declare the plug-in class. The plug-in class inherits from QObject and the interface implemented by the plug-in.
B. Use the macro Q_INTERFACES() to tell the Qt meta object system about the plug-in interface.
C. Use the macro Q_EXPORT_PLUGIN2() to export the plug-in class.
D. Build the plugin with the appropriate .pro file.
Before loading the plugin, the QCoreApplication object must be initialized.

2. Examples of plug-in development

1. Create a project

Create a project, select "Other Project" -> "Subdirs Project", fill in the project name as PluginApp, and select the save directory.
Qt Advanced - Qt Plugin Development

2. Create an application project

Right-click on the PluginApp project and select the "New Subproject" menu item, choose to create a GUI application, and the project name is MainWindow.
Qt Advanced - Qt Plugin Development
Fill in the name of the project application
Qt Advanced - Qt Plugin Development
Fill in the name of the main interface class:
Qt Advanced - Qt Plugin Development
add an interface Echonterface.h to the MainWindow application.

#ifndef ECHOINTERFACE_H
#define ECHOINTERFACE_H

#include <QString>

//定义接口
class EchoInterface
{
public:
    virtual ~EchoInterface() {}
    virtual QString echo(const QString &message) = 0;
};

#define EchoInterface_iid "Examples.Plugin.EchoInterface"

QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(EchoInterface, EchoInterface_iid)
QT_END_NAMESPACE

#endif // ECHOINTERFACE_H

3. Create a plug-in sub-project

Right-click on the PluginApp project and select the "New Subproject" menu item, and choose to create an empty Qt project named EchoPlugin.
Qt Advanced - Qt Plugin Development
The content of the EchoPlugin.pro project file is as follows:

TEMPLATE        = lib
CONFIG         += plugin
QT             += widgets
INCLUDEPATH    += ../MainWindow
TARGET          = $$qtLibraryTarget(echoplugin)
DESTDIR         = ../plugins

Add a plug-in class EchoPlugin to the plug-in sub-project, which is implemented as follows:
EchoPlugin.h file:

#ifndef ECHOPLUGIN_H
#define ECHOPLUGIN_H

#include <QObject>
#include <QtPlugin>
#include "EchoInterface.h"

class EchoPlugin : public QObject, public EchoInterface
{
    Q_OBJECT
    Q_INTERFACES(EchoInterface)
public:
    explicit EchoPlugin(QObject *parent = 0);
    QString echo(const QString &message);
};

#endif // ECHOPLUGIN_H

EchoPlugin.cpp file:

#include "EchoPlugin.h"

EchoPlugin::EchoPlugin(QObject *parent) :
    QObject(parent)
{
}

QString EchoPlugin::echo(const QString &message)
{
    return message;
}

Q_EXPORT_PLUGIN2(EchoPlugin, EchoPlugin);

4. Implementation of the application

Implement the MainWindow main interface
Widget.h file:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "EchoInterface.h"

QT_BEGIN_NAMESPACE
class QString;
class QLineEdit;
class QLabel;
class QPushButton;
class QGridLayout;
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void sendEcho();

private:
    void createGUI();
    //加载插件
    bool loadPlugin();

    EchoInterface *echoInterface;
    QLineEdit *lineEdit;
    QLabel *label;
    QPushButton *button;
    QGridLayout *layout;
};

#endif // WIDGET_H

Widget.cpp file:

#include "Widget.h"
#include <QtGui>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    createGUI();
    setLayout(layout);
    setWindowTitle("Echo Plugin Example");

    if (!loadPlugin())
    {
        QMessageBox::information(this, "Error", "Could not load the plugin");
        lineEdit->setEnabled(false);
        button->setEnabled(false);
    }
}
void Widget::sendEcho()
{
    QString text = echoInterface->echo(lineEdit->text());
    label->setText(text);
}

void Widget::createGUI()
{
    lineEdit = new QLineEdit;
    label = new QLabel;
    label->setFrameStyle(QFrame::Box | QFrame::Plain);
    button = new QPushButton(tr("Send Message"));

    connect(lineEdit, SIGNAL(editingFinished()),
            this, SLOT(sendEcho()));
    connect(button, SIGNAL(clicked()),
            this, SLOT(sendEcho()));

    layout = new QGridLayout;
    layout->addWidget(new QLabel(tr("Message:")), 0, 0);
    layout->addWidget(lineEdit, 0, 1);
    layout->addWidget(new QLabel(tr("Answer:")), 1, 0);
    layout->addWidget(label, 1, 1);
    layout->addWidget(button, 2, 1, Qt::AlignRight);
    layout->setSizeConstraint(QLayout::SetFixedSize);
}

bool Widget::loadPlugin()
{
    bool ret = true;
    //获取当前应用程序所在路径
    QDir pluginsDir(qApp->applicationDirPath());
#if defined(Q_OS_WIN)
    if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
        pluginsDir.cdUp();
#elif defined(Q_OS_MAC)
    if (pluginsDir.dirName() == "MacOS")
    {
        pluginsDir.cdUp();
        pluginsDir.cdUp();
        pluginsDir.cdUp();
    }
#elif defined(Q_OS_LINUX)
    pluginsDir.cdUp();
#endif
    //切换到插件目录
    pluginsDir.cd("plugins");
    //遍历plugins目录下所有文件
    foreach (QString fileName, pluginsDir.entryList(QDir::Files))
    {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));

        QObject *plugin = pluginLoader.instance();
        if (plugin)
        {
            //插件名称
            QString pluginName = plugin->metaObject()->className();
            //对插件初始化
            if(pluginName == "EchoPlugin")
            {
                echoInterface = qobject_cast<EchoInterface *>(plugin);
                if (echoInterface)
                    ret =  true;
                break;
            }
            else
            {
                ret = false;
            }
        }
    }
    return ret;
}

Widget::~Widget()
{

}

Main.cpp file:

#include "Widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

The program running results are as follows:
Qt Advanced - Qt Plugin Development
Check the build directory, and the generated plug-in files are stored in the plugins directory:
Qt Advanced - Qt Plugin Development

Third, the positioning plug-in

Qt applications will automatically sense available plugins, since plugins are stored in standard subdirectories. So the application doesn't need any code to find or load plugins.
During the development process, the plug-in directory is QTDIR/plugins (QTDIR is the installation directory of Qt), and each type of plug-in is placed under the corresponding type of directory. If you want the application to use plug-ins, but do not want to use the standard plug-in storage path, you can specify the path of the plug-in to be used during the installation process of the application. You can use QSettings to save the plug-in path and read the configuration file when the application is running. . The application can load the specified plugin path into the application through the QCoreApplication::addLibraryPath() function.
One way to make plugins loadable is to create a subdirectory in the directory where the application is located, where the plugins are stored. If you want to distribute any plugins in the plugins distributed with Qt (stored in the plugins directory), you must copy the plugins subdirectory of the plugins directory to the root directory of the application.

Fourth, static plug-ins

1. Introduction to static plugins

The usual and most flexible way to use a plugin with an application is to compile the plugin into a dynamic library that can be transferred independently and detected and loaded at runtime.
Plugins can be statically linked to applications. Building a static version of Qt is the only option to include Qt's predefined plugins. Using static plugins makes deployment less error-prone, but has the disadvantage that functionality not present in the plugin cannot be added with a full recompile and redistribution of the application.
Qt provides the following static plugins:
Qt Advanced - Qt Plugin Development

2. Use of static plugins

To statically link static plug-ins, you must use the Q_IMPORT_PLUGIN macro in the application, and you need to use QTPLUGIN to add the corresponding plug-ins to the project. Such as:

#include <QtPlugin>

Q_IMPORT_PLUGIN(qjpeg)
Q_IMPORT_PLUGIN(qgif)

In the .pro project file,

QTPLUGIN     += qjpeg \
                qgif

3. Create a static plugin

Use the following steps to create a static plug-in:
A. Add CONFIG += static to the .pro project file 
B. Use the Q_IMPORT_PLUGIN() macro to import the static plug-
in in the application C. Use LIBS to link the application in the application.pro project file Programs and static plugins.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324869501&siteId=291194637