看了一天,总结了下,可能有理解不到位的地方,仅供参考。我的理解插件开发主要分三块,插件接口,插件,主程序,uml如下图所示。
1、插件接口
插件接口主要关联接口和标识符,并提供声明一些通用辅助函数。
#ifndef PLUGININTERFACE
#define PLUGININTERFACE
#include <QString>
// 定义接口
class PluginInterface
{
public:
virtual ~PluginInterface() {}
virtual QString test(const QString &message) = 0;
};
// 关联接口和标识符
#define PluginInterface_iid "Examples.Plugin.PluginInterface"
QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(PluginInterface, PluginInterface_iid)
QT_END_NAMESPACE
#endif // PLUGININTERFACE
值得注意的是,这个头文件主程序和插件都需要引用(插件实现接口,主程序聚合关联接口),放到一个公共的文件夹比较好。
2、插件
插件实现接口中的方法,然后实现插件自身的业务。下面的插件只做测试,没有自身的业务。
2.1、testplugin.pro
TEMPLATE = lib
CONFIG += plugin
QT += widgets
TARGET = $$qtLibraryTarget(testplugin)
DESTDIR = ../plugins
HEADERS += \
testplugin.h
SOURCES += \
testplugin.cpp
2.2、testplugin.h
#ifndef TESTPLUGIN_H
#define TESTPLUGIN_H
#include <QObject>
#include <QtPlugin>
#include <QString>
#include "../worker/plugininterface.h"
class TestPlugin :public QObject, public PluginInterface
{
Q_OBJECT
Q_INTERFACES(PluginInterface)
public:
TestPlugin(QObject *parent = 0);
QString test(const QString& msg);
};
#endif // TESTPLUGIN_H
2.3、testplugin.cpp
#include "testplugin.h"
#include <QDebug>
TestPlugin::TestPlugin(QObject *parent)
{
}
QString TestPlugin::test(const QString &msg)
{
qDebug() << msg;
return tr("plugin return ") + msg;
}
Q_EXPORT_PLUGIN2(TestPlugin, TestPlugin);
3、主程序
主程序主要功能是加载插件
3.1、worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QMainWindow>
#include "plugininterface.h"
namespace Ui {
class Worker;
}
class Worker : public QMainWindow
{
Q_OBJECT
public:
explicit Worker(QWidget *parent = 0);
~Worker();
bool loadPlugins();
private slots:
void on_pushButton_clicked();
private:
Ui::Worker *ui;
PluginInterface *testPlugin;// 插件对象
};
#endif // WORKER_H
3.2、worker.cpp
#include "worker.h"
#include "ui_worker.h"
#include <QDir>
#include <QApplication>
#include <QPluginLoader>
#include <QDebug>
Worker::Worker(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Worker)
{
ui->setupUi(this);
loadPlugins();
}
Worker::~Worker()
{
delete ui;
if (testPlugin)
delete testPlugin;
}
bool Worker::loadPlugins()
{
bool ret = true;
//获取当前应用程序所在路径
QDir pluginsDir(qApp->applicationDirPath());
//切换到插件目录
pluginsDir.cd("plugins");
//遍历plugins目录下所有文件
foreach (QString fileName, pluginsDir.entryList(QDir::Files))
{
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
qDebug() << tr("start load plugin from %1").arg(fileName);
QObject *plugin = pluginLoader.instance();
if (plugin)
{
qDebug() << tr("load plugin from %1 success").arg(fileName);
//插件名称
QString pluginName = plugin->metaObject()->className();
//对插件初始化
if(pluginName == "TestPlugin")
{
testPlugin = qobject_cast<PluginInterface *>(plugin);
if (testPlugin)
ret = true;
break;
}
else
{
qDebug() << tr("Failed to load plugin from %1").arg(fileName);
ret = false;
}
}
else
{
qDebug() << tr("Failed to load plugin from %1, for %2").arg(fileName).arg(pluginLoader.errorString());
ret =false;
}
}
return ret;
}
void Worker::on_pushButton_clicked()
{
QString msg = ui->lineEdit->text();
if (testPlugin)
qDebug() << testPlugin->test(msg);
}
4、运行结果