Hello Qt -- Qt plug-in development

1, Qt plug-in mechanism

1. Introduction to Qt plug-in

Plug in is a program written according to a certain standard application program interface, which is positioned to develop and realize the functions that the application software platform does not have.

2. Qt plug-in API

Qt provides two APIs for creating plug-ins: one is a high-level API, which is used to expand the functions of Qt itself, such as custom database driver, image format, text coding, custom style, etc; One is a low-level API for extending Qt applications.

3. Extend application functionality through plug-ins

A. There is only one class (virtual set) used to communicate with the plug-in.
B. Use macro Q_DECLARE_INTERFACE() tells the Qt meta object system of this interface.

C. QPluginLoader is used to load plug-ins in the application.

D. Use macro qobject_cast() to determine whether a plug-in implements an interface.

4. Create plug-in

The steps to create a plug-in are as follows:

A. Declare the plug-in class, which inherits from QObject and the interface implemented by the plug-in.
B. Use macro Q_INTERFACES() tells the Qt meta object system of the plug-in interface.

C. Use macro Q_EXPORT_PLUGIN2() exports the plug-in class.

D. Use the appropriate pro file build plug-in.

The QCoreApplication object must be initialized before loading the plug-in.

2, Plug in development example

1. Create project

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

2. Create application engineering

Right click the PluginApp project, select "New Subproject" menu item, and select Create a GUI application. The project name is MainWindow.

Fill in the name of engineering application

Fill in the name of the main interface class:

Add an interface echointerface in MainWindow application h.

#ifndef ECHOINTERFACE_H
#define ECHOINTERFACE_H

#include <QString>

//Interface definition
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 plug-in subproject

Right click the PluginApp project, select the menu item "new subject", and select Create an empty Qt project named EchoPlugin.

 EchoPlugin. The contents of Pro engineering documents are as follows:

TEMPLATE        = lib

CONFIG         += plugin

QT             += widgets

INCLUDEPATH    += ../MainWindow

TARGET          = $$qtLibraryTarget(echoplugin)

DESTDIR         = ../plugins

Add a plug-in class EchoPlugin in the plug-in subproject, and the implementation is as follows:

EchoPlugin.h documents:

#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. Application implementation

Implement MainWindow main interface

Widget.h documents:

#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();
    //Loading plug-ins
    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;
    //Get the path where the current application is located
    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

    //Switch to plug-in directory
    pluginsDir.cd("plugins");
    //Traverse all files in plugins directory
    foreach (QString fileName, pluginsDir.entryList(QDir::Files))
    {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        if (plugin)
        {
            //Plug in name
            QString pluginName = plugin->metaObject()->className();
            //Initialize the plug-in
            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 running results of the program are as follows:

Check the build directory, and the generated plug-in files are stored in the plugins directory:

III. positioning plug-in

Qt applications will automatically sense the available plug-ins because they are stored in standard subdirectories. Therefore, the application does not need any code to find or load plug-ins.

During the development process, the directory of plug-ins is QTDIR/plugins(QTDIR is the installation directory of Qt), and each type of plug-in is placed under the directory of the corresponding type. If you want the application to use the plug-in, 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 of the application. You can use qssettings to save the plug-in path and read the configuration file when the application is running. The application can load the specified plug-in path into the application through the QCoreApplication::addLibraryPath() function.

One way to make plug-ins loadable is to create a subdirectory in the directory where the application is located to store plug-ins. If you want to publish any plug-ins in the plug-ins published with Qt (stored in the plugins directory), you must copy the plug-in subdirectory under the plugins directory to the root directory of the application.

4, Static plug-in

1. Introduction to static plug-ins

The usual and most flexible way to use a plug-in with an application is to compile the plug-in into a dynamic library, which can be transferred independently and detected and loaded at run time.

Plug ins can be statically linked to applications. Building a static version of Qt is the only option for predefined plug-ins that contain Qt. The use of static plug-ins makes the deployment less error prone, but the disadvantage is that the functions not in the plug-ins cannot be added when the application is fully recompiled and republished.

Qt provides the following static plug-ins:

2. Use of static plug-ins

To statically link static plug-ins, you must use Q in your application_ IMPORT_ Plug in macro. At the same time, qtplug in needs to be used to add corresponding plug-ins to the project. For example:

#include <QtPlugin>



Q_IMPORT_PLUGIN(qjpeg)

Q_IMPORT_PLUGIN(qgif)

Yes In pro engineering documents,

QTPLUGIN     += qjpeg \
                qgif

3. Create static plug-ins

Use the following steps to create a static plug-in:

A. Yes Add CONFIG += static in pro project file

B. Using {Q in applications_ IMPORT_ Plugin() macro import static plug-in

C. In the application pro project files use LIBS to link applications and static plug-ins.

Keywords: Qt

Added by DannyM on Sun, 06 Mar 2022 18:59:46 +0200