目录

  • 插件简介
  • 创建插件
  • 加载使用插件
  • QPluginLoader


插件简介

插件最大的功能是提高了软件的灵活度和扩展性,软件可以在不停止的情况下,通过加入插件增加新的功能实现升级换代。
QT的插件分为两种,一种是高级的插件,另一种是低级的插件,低级的插件需要自己编写接口,下面插件的介绍以低级插件为例。

在面向对象的角度看,所谓的插件就是按照特定的接口编写的子类,且该接口必须是虚基类,且所有函数(除了析构)都是虚函数。而插件就是继承该虚基类和QObject的子类。当程序调用该插件的某个函数时,是通过该插件的虚基类在运行时动态绑定至子类的虚表执行的,这也是继承和多态的表现形式。

创建插件

  1. 新建一个库项目
  2. 在.pro文件加入
CONFIG += plugin
DEFINES += MEDIAN_FILTER_PLUGIN_LIBRARY
  1. 创建定义一个接口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
  1. 修改插件类头文件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
  1. 修改plugina.cpp文件
#include "plugina.h"
Plugina::~Plugina()
{}
QString Plugina::description(){
    return "This plugin applies median blur filters to any image.";
}
  1. 保存文件,右键项目,选择重新构建,即可生成一个plugina.dll文件

加载使用插件

使用plugin插件需要接口头文件 myplugina.h和plugina.dll两个文件。

  1. 将myplugina.h文件复制到一个qt项目的头文件目录下,然后右击头文件目录,选择添加现有文件,然后将myplugina.h添加进去。
  2. 在mainwindow.h添加头文件
#include "myplugina.h"
  1. 在mainwindow.h添加私有方法声明
void getplugin(QString pluginpath);
  1. 在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;
}
  1. 在某个函数中调用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()

卸载插件