QT Plugin hot swap plug-in

        What is the difference between hot-loading plugins and dynamically loading DLLs in QT? The hot loading plug-in is to dynamically load the plug-in when the program is running, and the dynamic loading of the DLL is to link the DLL file into the program when the program is compiled. Hot loading plug-ins can update plug-ins without stopping the program, while dynamically loading DLLs requires recompiling the program to update the DLL file.

        How to hot load plugin in QT to update the plugin without stopping the program? Use the QPluginLoader class to implement hot-loading plugins. When the program is running, use QPluginLoader to load the plug-in, and use the QObject::connect() function to connect the signal and slot of the plug-in. When the plug-in needs to be updated, you can use the QPluginLoader::unload() function to unload the old plug-in, and then use QPluginLoader again to load the new plug-in. This makes it possible to update plugins without stopping the program.

        Personally understand that when using a DLL dynamic library in an actual project, if you need to update or replace it, you need to close the program and replace the DLL before restarting the program. Generally, it may be fine, but some special scenarios require 24-hour work or communication, and there are always tasks running It is not suitable to close the main program. In this case, the hot-swappable plug-in function of QT Plugin is very much needed. Without restarting the program, adding a setting button and connecting a signal slot on the setting interface can realize dynamic update of the plug-in without stopping the program.

 The author of this article is original, please attach the source of the article and the link of this article for reprinting.

QT Plugin hot plug-in directory

1 QPluginA

1.1 QPluginA.pro

1.2 DeclareInterface.h

1.3 qplugina.h

1.4 qplugina.cpp

2 QPluginB

2.1 QPluginB.pro

2.2 DeclareInterface.h

2.3 qpluginb.h

2.4 qpluginb.cpp

3 QMainPlugin

3.1 QMainPlugin.pro

3.2 DeclareInterface.h

3.3 mainwindow.h

3.4 mainwindow.cpp


1 QPluginA

        Plugin A source code

1.1 QPluginA.pro

QT += core
QT += gui
QT             += widgets


TEMPLATE = lib
CONFIG += plugin
TARGET = HelloCTK


CONFIG += c++11


EXAMPLE_FILES = qtplugin.json




greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    qplugina.cpp

HEADERS += \
    DeclareInterface.h \
    QPluginA_global.h \
    qplugina.h

# Default rules for deployment.
unix {
    target.path = /usr/lib
}
!isEmpty(target.path): INSTALLS += target

1.2 DeclareInterface.h

//declareinterface.h
#ifndef DECLAREINTERFACE_H
#define DECLAREINTERFACE_H


#include <QWidget>

//定义接口
class DeclareInterface
{
public:
    virtual ~DeclareInterface() {}
    virtual int add(int a,int b) = 0;
};

//一定是唯一的标识符
#define DeclareInterface_iid "Examples.Plugin.DeclareInterface"

QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(DeclareInterface, DeclareInterface_iid)
QT_END_NAMESPACE

#endif // DECLAREINTERFACE_H

1.3 qplugina.h

#ifndef QPLUGINA_H
#define QPLUGINA_H

#include "QPluginA_global.h"
#include <QObject>
#include <QtPlugin>
#include "DeclareInterface.h"

class  QPluginA : public QObject, public DeclareInterface
{
    Q_OBJECT
    Q_INTERFACES(DeclareInterface)
    Q_PLUGIN_METADATA(IID  "qtplugin.json")


public:

    QPluginA(QObject *parent = 0);
    int add(int a, int b);


};

#endif // QPLUGINA_H

1.4 qplugina.cpp

#include "qplugina.h"

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

int QPluginA::add(int a, int b)
{
    return a+b;
}

2 QPluginB

        Plugin B source code

2.1 QPluginB.pro

QT += core
QT += gui
QT             += widgets


TEMPLATE = lib
CONFIG += plugin
TARGET = HelloCTKS


CONFIG += c++11


EXAMPLE_FILES = qtplugin.json
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    qpluginb.cpp

HEADERS += \
    DeclareInterface.h \
    QPluginB_global.h \
    qpluginb.h

# Default rules for deployment.
unix {
    target.path = /usr/lib
}
!isEmpty(target.path): INSTALLS += target

2.2 DeclareInterface.h

//declareinterface.h
#ifndef DECLAREINTERFACE_H
#define DECLAREINTERFACE_H


#include <QWidget>

//定义接口
class DeclareInterface
{
public:
    virtual ~DeclareInterface() {}
    virtual int add(int a,int b) = 0;
};

//一定是唯一的标识符
#define DeclareInterface_iid "Examples.Plugin.DeclareInterface"

QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(DeclareInterface, DeclareInterface_iid)
QT_END_NAMESPACE

#endif // DECLAREINTERFACE_H

2.3 qpluginb.h

#ifndef QPLUGINB_H
#define QPLUGINB_H

#include "QPluginB_global.h"
#include <QObject>
#include <QtPlugin>
#include "DeclareInterface.h"

class  QPluginB : public QObject, public DeclareInterface
{
public:
    Q_OBJECT
    Q_INTERFACES(DeclareInterface)
    Q_PLUGIN_METADATA(IID  "qtplugin.json")


public:

    QPluginB(QObject *parent = 0);
    int add(int a, int b);
};

#endif // QPLUGINB_H

2.4 qpluginb.cpp

#include "qpluginb.h"

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

int QPluginB::add(int a, int b)
{
    return a-b;
}

3 QMainPlugin

        project source code

3.1 QMainPlugin.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    DeclareInterface.h \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

3.2 DeclareInterface.h

//declareinterface.h
#ifndef DECLAREINTERFACE_H
#define DECLAREINTERFACE_H


#include <QWidget>

//定义接口
class DeclareInterface
{
public:
    virtual ~DeclareInterface() {}
    virtual int add(int a,int b) = 0;
};

//一定是唯一的标识符
#define DeclareInterface_iid "Examples.Plugin.DeclareInterface"

QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(DeclareInterface, DeclareInterface_iid)
QT_END_NAMESPACE

#endif // DECLAREINTERFACE_H

3.3 mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <QDir>
#include <QDebug>
#include <QMessageBox>
#include <QPluginLoader>

#include "DeclareInterface.h"

#pragma execution_character_set("utf-8")
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

private:
    Ui::MainWindow *ui;

    QPluginLoader pluginLoader;

    bool loadPlugin(QString strPlugin);   //加载插件
    DeclareInterface* m_pInterface = nullptr;  //获取插件类型
};
#endif // MAINWINDOW_H

3.4 mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);



}

MainWindow::~MainWindow()
{
    delete ui;
}

bool MainWindow::loadPlugin(QString strPlugin){

    pluginLoader.setFileName(strPlugin);
    QObject *plugin = pluginLoader.instance();
    qDebug() << __FUNCTION__ << pluginLoader.errorString();
    if (plugin) {
        m_pInterface = qobject_cast<DeclareInterface *>(plugin);
        if (m_pInterface)
            return true;
    }
    return false;
}


void MainWindow::on_pushButton_clicked()
{
    int a = 5;
    int b = 5;
    int r = -1;
    if(m_pInterface){
        r = m_pInterface->add(a, b);
    }
    QMessageBox::warning(this, "插件调用成功", QString::number(r));

}

void MainWindow::on_pushButton_2_clicked()
{
    pluginLoader.unload();
    if(!loadPlugin("HelloCTK.dll")){
        QMessageBox::warning(this, "Error", "Could not load the plugin");
    }

}

void MainWindow::on_pushButton_3_clicked()
{
    pluginLoader.unload();
    if(!loadPlugin("HelloCTKS.dll")){
        QMessageBox::warning(this, "Error", "Could not load the plugin");
    }
}

PS: Program effect diagram PluginA implements subtraction PluginB implements addition

Supongo que te gusta

Origin blog.csdn.net/qq_37529913/article/details/129605982
Recomendado
Clasificación