Qt 插件系統的使用和簡單示例

0. 前言

Qt 有自己的插件系統, 使用插件框架開發程序, 便於擴展和管理, 插件實際上是動態庫, 個人理解是與動態庫的區別是有一個插件管理器, 使用相同的調用約定.

 

1. 環境

Qt 4.8.7 + win10

 

2. 功能

這個demo的功能是發送一個Message字符串到插件的函數, 並返回顯示
 

3.目錄

源碼路徑: Github下載源碼地址

E:PluginApp
│  list.txt
│  PluginApp.pro
│  PluginApp.pro.user
│  
├─EchoPlugin
│      echoplugin.cpp
│      echoplugin.h
│      EchoPlugin.pro
│      main.cpp
│      
└─MainWindow
        echointerface.h
        main.cpp
        MainWindow.pro
        widget.cpp
        widget.h

可以看到, 使用了子項目開發模式, PluginApp 內有兩個子項目, EchoPlugin和MainWindow

EchoPlugin: 插件子項目, 生成dll插件

MainWindow: 主窗口 , 調用插件

 

4. 用法

先不說細節, 只講大概的思路

EchoPlugin

<1> pro中插件的相應配置

<2> 創建插件類, 實現相關的方法

MainWindow

<1> 定義插件的調用頭文件, 裏面是插件類的聲明, 都是虛方法, 用於在創建插件對象時重載

<2> 加載插件類並使用

 

5. 源碼

上部分核心代碼

MainWindow子項目

echointerface.h 聲明插件虛方法的頭文件

#ifndef ECHOINTERFACE_H
#define ECHOINTERFACE_H

#include <QString>

class EchoInterface
{
public:
    virtual ~EchoInterface() {}
    virtual QString echo(const QString &message) = 0;
};

#define EchoInterface_lib "Example.Plugin.EchoInterface"

QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(EchoInterface, EchoInterface_lib)
QT_END_NAMESPACE

#endif // ECHOINTERFACE_H

loadPlugin() 加載插件

bool Widget::loadPlugin()
{
    bool ret = true;
    //獲取當前應用程序所在路徑
    QDir pluginsDir(qApp->applicationDirPath());
    qDebug() << pluginsDir;

#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.cdUp();
    pluginsDir.cd("plugins");
    qDebug() << pluginsDir;

    //遍歷plugins目錄下所有文件
    foreach (QString fileName, pluginsDir.entryList(QDir::Files))
    {
        qDebug() << fileName;
        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;
}

sendEcho 使用插件方法

void Widget::sendEcho()
{
    QString text = echoInterface->echo(lineEdit->text());
    label->setText(text);
}

 

EchoPlugin 插件子項目

echointerface.h

#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

echointerface.cpp

#include "echoplugin.h"

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

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

Q_EXPORT_PLUGIN2(EchoPlugin, EchoPlugin)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章