QT 插件简介
什么是插件
插件机制是一种扩展现有程序的机制。插件允许第三方开发者在无需访问主程序源代码的情况下来扩展该程序。插件能够应用的各项服务,包括提供加载方式,使插件可以加载到应用程序和网络传输协议中,从而和插件进行数据交换等。简而言之,插件是提供特定接口的库。
QT插件的两种类型:
Qt Plugin和其他类型的插件一样,是一种计算机应用程序,它和主应用程序(host application)互相交互,以提供特定的功能。应用程序支持Plugin有许多原因,一些主要原因包括:使得第三方开发者有能力扩展应用程序,以提供无法先期预料的特色;减小应用程序的大小;由于软件版权之间的不兼容性将源代码和应用程序分享。Qt Plugin 分动态插件和静态插件两种。
1.静态插件能够静态的链接到应用程序,使得部署更少出错,但是应用程序重新构建和发布时难以增加新的功能;
2.动态插件是更常用到和更灵活的方式,可以单独发布,并且可以在运行时检测和加载;
QT插件的实现步骤
如何去实现一个动态插件
1 定义接口类:
1.1.定义共同接口(纯虚类):
程序要能感知插件,需要程序和插件共同遵守某种规则。于是需要在主程序中定义一个共同的接口,该接口直接和插件类交流;
本例中定义一个QContactPlugin interface
//QContactPluginInterface.h
#include
class QContactPluginInterface
{
public:
virtual ~ QContactPluginInterface () {}
virtual int getContact(int v) = 0;
};
1.2.使用宏Q_DECLARE_INTERFACE()
在QContactPluginInterface.h中添加以下代码:
Q_DECLARE_INTERFACE(QContactPluginInterface, "com.intel.Plugin. QContactPluginInterface ");
Q_DECLARE_INTERFACE定义在在qobject.h中,用来告诉Qt meta-object system 这个接口名称.
2.主程序部分:
主程序部分动态加载插件的代码如下:
QDir pluginsDir(qApp->applicationDirPath());
foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = pluginLoader.instance();
if (plugin) {
QContactPluginInterface *interface = qobject_cast(plugin);
if (interface) {
qDebug()< getContact (10);
}
}
}
以上这段代码主要包含以下几个步骤:
2.1.到指定路径搜索插件
QDir pluginsDir(qApp->applicationDirPath());
foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
2.2.检测并加载插件.
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
2.3.测试插件是否有效
使用 qobject_cast()测试插件是否给出了相应接口并进行类型转换,转换成接口对象指针.
QContactPluginInterface *interface = qobject_cast(plugin);
if (interface) {
qDebug()< getContact (10);
}
#p#
3.编写插件:
pluginXX.h
//Exampel, pluginXX.h
#include
#include " QContactPluginInterface.h"
class PluginXX:public QObject, public QContactPluginInterface
{
Q_OBJECT
Q_INTERFACES(QContactPluginInterface)
public:
PluginXX(QObject *parent=NULL);
int getContact (int v);
};
pluginXX.cpp
// Exampel pluginXX.cpp
#include "pluginXX.h"
PluginXX::PluginXX(QObject *parent)
:QObject(parent)
{
}
int PluginXX::getContact(int v)
{
//todo
return XXNumber;
}
Q_EXPORT_PLUGIN2(pluginXX, PluginXX);
以上这段代码主要包含以下几个步骤:
3.1.声明插件类,
#include
#include " QContactPluginInterface.h"
class PluginXX:public QObject, public QContactPluginInterface
这个类继承QObject 类和接口类,同时注意,需要将接口类的头文件包含。
3.2.使用宏Q_INTERFACES()
Q_INTERFACES(QContactPluginInterface)
Q_INTERFACES 使用在定义接口类时通过Q_DECLARE_INTERFACE声明过的接口。它同样是用来告诉Qt的moc系统,将使用QContactPluginInterface这个接口。
3.3.输出插件
Q_EXPORT_PLUGIN2(pluginXX, PluginXX);
使用宏 Q_EXPORT_PLUGIN2()是让Qt知道PluginXX是一个插件,第一个参数是插件的名字,第二个参数是库的名字,所以二者经常是相同的。
3.4.构建插件.
#pluginXX.pro
TEMPLATE = lib
CONFIG += plugin
INCLUDEPATH += ../XX
HEADERS = pluginXX.h
SOURCES = pluginXX.cpp
DESTDIR = ../
由以上.pro文件,Qt会自动将其编译为动态插件,在主程序运行时动态加载。