Qt为创建插件提供了两个api:
1、为Qt本身编写扩展的高级API:自定义数据库驱动程序、图像格式、文本编解码器、自定义样式等等。
2、用于扩展Qt应用程序的低级API。
例如,如果您想编写一个定制的QStyle子类并让Qt应用程序动态地加载它,那么您将使用更高级别的API。
由于较高级别的API构建在较低级别的API之上,因此两者都存在一些共同的问题。
一、高级API:编写Qt扩展
编写扩展Qt本身的插件是通过子类化适当的插件基类、实现一些函数和添加宏来实现的。
二、低级API:扩展Qt应用程序
不仅Qt本身,Qt应用程序也可以通过插件进行扩展。这要求应用程序使用QPluginLoader检测和加载插件。在这种情况下,插件可以提供任意的功能,不限于数据库驱动程序、图像格式、文本编解码器、样式和其他扩展Qt功能的插件类型。
通过插件使应用程序可扩展涉及以下步骤:
1、定义一组用于与插件对话的接口(只有纯虚函数的类)。
2、使用Q_DECLARE_INTERFACE()宏告诉Qt的元对象系统关于接口的信息。
3、在应用程序中使用QPluginLoader来加载插件。
4、使用qobject_cast()测试插件是否实现给定的接口。
编写插件包括以下步骤:
1、声明一个插件类,它继承自QObject和插件想要提供的接口。
2、使用Q_INTERFACES()宏告诉Qt的元对象系统关于接口的信息。
3、使用Q_PLUGIN_METADATA()宏导出插件。
4、使用合适的.pro文件构建插件。
三、如何加载插件
方法1、创建一个目录,将插件放在该目录中。在程序运行时,使用QPluginLoader加载该路径内的插件即可。
方法2、将插件放在某个路径下,在程序启动时,使用QCoreApplication::addLibraryPath()添加该路径,然后直接使用QPluginLoader调用插件名称即可。
记录一下操作:
1、编写接口
class MyPluginInterface
{
public:
virtual ~MyPluginInterface(){}
virtual QString getHello() = 0;
};
Q_DECLARE_INTERFACE(MyPluginInterface,"MyPluginInterface_Only_One")
//最后一行的Q_DECLARE_INTERFACE宏告诉Qt这个纯虚类是一个插件接口。
//第一个参数是接口类名,第二个参数是插件标识符,标识符是大小写敏感的且必须是唯一的。
2、编写插件类:
class MyPlugin : public QObject, public MyPluginInterface
{
Q_OBJECT
//实现类必须继承自QObject和插件接口类。Q_PLUGIN_METADATA宏用于描述插件元数据,
//第一个参数IID是必须的,同插件标识一样
//而第二个参数FILE是可选的,指定一个本地json文件,该文件中可以描述插件的相关数据信息
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "MyPluginInterface_Only_One" FILE "MyPlugin.json")
#endif // QT_VERSION >= 0x050000
Q_INTERFACES(MyPluginInterface)
public:
MyPlugin(QObject *parent = 0);
virtual QString getHello() override;
};
MyPlugin::MyPlugin(QObject *parent) :
QObject(parent)
{
}
QString MyPlugin::getHello()
{
return QString("hello myplugin");
}
3、在程序中动态加载
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//第一种方法
// QCoreApplication::addLibraryPath("../plugins");//将程序的插件路径添加到Qt的搜索路径中
// QPluginLoader loader("MyPlugin.dll");
//第二种
QPluginLoader loader("../plugins/MyPlugin.dll");
if(loader.load()){
QObject *obj = loader.instance();
if(obj != 0){
MyPluginInterface *plugin = qobject_cast<MyPluginInterface*>(obj);
if(plugin != 0){
qDebug() << plugin->getHello();
}
}
delete obj;
}else{
qDebug() << "加载插件失败...";
}
return a.exec();
}