前言
今天想看一些Qt插件系统。看了之后发现Qt支持两种插件方式:高级API和低级API。 高级API指的的为Qt软件本身定制插件; 低级API指的是为自己写的软件定制插件。 这篇文章主要讲的是如何编写使用一个低级API,文章属于入门级的,只是简单使用。
Qt插件和动态库区别(查找的)
Qt插件本身是动态库,除此之外,它定义了一组专用的接口,从动态库中导出,供 Qt 的插件管理体系发现和调用。当你选择 Qt 插件项目模板时, Qt Creator 会自动为你插入专用接口相关的模板代码。
假如你从一个白板做起,实现一个动态库,要想客户方调用,还是需要导出N多的函数。而 Qt 这种,只是它约定了你需要导出什么函数、什么类、怎样查询你导出的接口,它定义了一套规范而已。原文地址: https://bbs.csdn.net/topics/390843246?page=1
新建一个插件
1. 新建一个C++库
2. 选择Qt Plugin
3. Qt插件名称,我这里是默认的根据需求来。下面的基类还没有研究过
编写插件代码(不要忘记看注释)
1. 新建一个头文件,作为插件导出的接口头文件。命名为: TestPluginBase.h。代码如下。
#ifndef TESTPLUGINBASE_H
#define TESTPLUGINBASE_H
class TestPluginBase
{
public:
virtual ~TestPluginBase() {}
virtual void test() = 0;
};
// Q_DECLARE_INTERFACE 告诉Qt这个纯虚类是一个插件接口类。
// 第一个参数: 接口类名
// 第二个参数: 插件标识符,标识符大小写敏感且必须唯一
Q_DECLARE_INTERFACE(TestPluginBase, "org.qt-project.Qt.QGenericPluginFactoryInterface/1.0")
#endif // TESTPLUGINBASE_H
2. 插件文件继承:QObject和TestPluginBase
头文件: GenericPlugin.h
#ifndef GENERICPLUGIN_H
#define GENERICPLUGIN_H
#include <QGenericPlugin>
#include <QObject>
#include "testpluginbase.h"
class GenericPlugin : public QObject, public TestPluginBase
{
Q_OBJECT
// 调用此宏之前必须存在一个Q_DECLARE_INTERFACE 声明的相应接口
Q_INTERFACES(TestPluginBase)
#if QT_VERSION >= 0x050000
// Q_PLUGIN_METADATA用于描述插件元数据
// 第一个参数: IID必须的
// 第二个参数: FILE可选的用于描述插件的相关信息
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface/1.0" FILE "TestPlugin.json")
#endif // QT_VERSION >= 0x050000
public:
GenericPlugin();
// 插件调用的方法。
// Q_DECL_OVERRIDE 用来声明这是一个对虚函数进行定义
// 的方法,编译器会验证该方法名是否是否父类中所有的,如果没有则报错 Q_DECL_OVERRIDE
void test();
};
#endif // GENERICPLUGIN_H
CPP文件
#include "genericplugin.h"
#include <QDebug>
GenericPlugin::GenericPlugin()
{
}
void GenericPlugin::test()
{
qDebug() << "[" << __FUNCTION__ <<__LINE__ << "] :" << "hello Qt plugin";
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(TestPlugin, GenericPlugin)
#endif // QT_VERSION < 0x050000
TestPlugin.json
{
"Keys" : [ ],
// 以下信息是我自己定义的
"Name" : "测试插件",
"Desc" : "插件描述",
"Author": "HBQ",
"HomeUrl": "https://itzhai.cn",
"UseDesc": "使用描述"
}
Pro文件修改
# DESTDIR = $$[QT_INSTALL_PLUGINS]/generic
DESTDIR = $$PWD/bin // jiang将上面的注释修改成下面的fangbian方便找
3. 点击工程运行,生成插件。注意看是否生成dll文件。
插件的使用
1. 新建一个Qt控制台程序,复制TestPluginBase.h头文件到新建的控制台项目,结构如下
2. 插件使用代码
#include <QCoreApplication>
#include <QDir>
#include <QPluginLoader>
#include <QDebug>
#include "testpluginbase.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QDir dir;
dir.setPath("./plugins");
if(!dir.exists()) { qDebug() << "[" << __FUNCTION__ <<__LINE__ << "] :" << "Plugin Path no exist!"; return -1;}
foreach (QString filename, dir.entryList(QDir::Files)) {
qDebug() << "[" << __FUNCTION__ <<__LINE__ << "] :" << dir.absoluteFilePath(filename);
QPluginLoader *loader = new QPluginLoader(dir.absoluteFilePath(filename));
if(!loader->load())
{
qWarning("%s is not a plugin",qPrintable(dir.absoluteFilePath(filename)));
continue;
}
QObject *obj = loader->instance();
TestPluginBase *plugin = qobject_cast<TestPluginBase *>(obj);
plugin->test(); // 调用插件方法
qDebug() << "[" << __FUNCTION__ <<__LINE__ << "] :" << loader->metaData(); // 解析json文件
}
return a.exec();
}
3. 在软件运行的Debug目录上层新建一个plugins文件,将插件dll放入其中
4. 运行测试程序
总结
仔细详细那插件还是很有用的。虽然目前还没用到,但是一直还是想看,接下来去看看高级API,Qt自己的插件。这里只是简单使用,我也很菜,如有误导可以在下方留言喷我。