目录
- 插件简介
- 创建插件
- 加载使用插件
- QPluginLoader
插件简介
插件最大的功能是提高了软件的灵活度和扩展性,软件可以在不停止的情况下,通过加入插件增加新的功能实现升级换代。
QT的插件分为两种,一种是高级的插件,另一种是低级的插件,低级的插件需要自己编写接口,下面插件的介绍以低级插件为例。在面向对象的角度看,所谓的插件就是按照特定的接口编写的子类,且该接口必须是虚基类,且所有函数(除了析构)都是虚函数。而插件就是继承该虚基类和QObject的子类。当程序调用该插件的某个函数时,是通过该插件的虚基类在运行时动态绑定至子类的虚表执行的,这也是继承和多态的表现形式。
创建插件
- 新建一个库项目
- 在.pro文件加入
CONFIG += plugin
DEFINES += MEDIAN_FILTER_PLUGIN_LIBRARY
- 创建定义一个接口myplugina.h
#ifndef CVPLUGININTERFACE_H
#define CVPLUGININTERFACE_H
#include <QObject>
#include <QString>
class MyInterface
{
public:
virtual ~CvPluginInterface(){}
virtual QString description() = 0;
};
#define CVPLUGININTERFACE_IID "com.amin.myinterface"
Q_DECLARE_INTERFACE(MyInterface,CVPLUGININTERFACE_IID) //告诉Qt这个纯虚类是一个插件接口
#endif // CVPLUGININTERFACE_H
- 修改插件类头文件plugina.h
#ifndef MEDIAN_FILTER_PLUGIN_H
#define MEDIAN_FILTER_PLUGIN_H
#include <QtPlugin>
#include "plugina_global.h"
#include "myplugina.h"
class PLUGINASHARED_EXPORT Plugina:
public QObject,public MyInterface//确保该类继承QObject和MyInterface
{
Q_OBJECT //允许Qt特定的功能(比如信号和槽)
Q_PLUGIN_METADATA(IID "com.amin.cvplugininterface") //需要在一个插件的源代码中刚好出现一次,用于添加关于插件的元数据
Q_INTERFACES(CvPluginInterface) //用于声明插件中实现的接口
public:
~Plugina() Q_DECL_OVERRIDE;
virtual QString description() Q_DECL_OVERRIDE;
};
#endif // MEDIAN_FILTER_PLUGIN_H
- 修改plugina.cpp文件
#include "plugina.h"
Plugina::~Plugina()
{}
QString Plugina::description(){
return "This plugin applies median blur filters to any image.";
}
- 保存文件,右键项目,选择重新构建,即可生成一个plugina.dll文件
加载使用插件
使用plugin插件需要接口头文件 myplugina.h和plugina.dll两个文件。
- 将myplugina.h文件复制到一个qt项目的头文件目录下,然后右击头文件目录,选择添加现有文件,然后将myplugina.h添加进去。
- 在mainwindow.h添加头文件
#include "myplugina.h"
- 在mainwindow.h添加私有方法声明
void getplugin(QString pluginpath);
- 在mainwindow.cpp文件内定义getplugin函数体
pluginpath的地址就是plugina.dll的地址
void MainWindow::getplugin(QString pluginpath){
QFile file(pluginpath);
if(!file.exists()){
QMessageBox::warning(this,"file is not found","error");
return ;
}
QPluginLoader loader(pluginpath); //在应用中加载插件
QObject *instance = loader.instance();
if(instance == nullptr){
QMessageBox::warning(this,"instance is not found","error");
return ;
}
CvPluginInterface *avc = qobject_cast<CvPluginInterface *>(instance); //来测试插件是否实现了给定的接口
ui->lineEdit_2->setText(avc->description());
delete instance;
}
- 在某个函数中调用getplugin即可
QPluginLoader
QPluginLoader类在运行时加载插件,提供对Qt插件的访问。
- 指定加载哪个插件
//构造函数
QPluginLoader(const QString &fileName, QObject *parent = nullptr);
//setFileName方法
void setFileName(const QString &fileName);
- 常用方法
方法 | 作用 |
QObject *instance() | 访问插件中的根组件 |
bool load() | 动态加载插件 |
bool isLoaded() const | 插件是否加载成功 |
bool unload() | 卸载插件 |