说明近期入职新公司,新公司的项目用到了Qt的插件系统,花时间了解了一下,还以为Qt的插件系统有多么高级呢,原来归根到底还是 dll 的动态调用时获取其中的类那一招啊,原理和之前的文章《DLL的动态加载》 的里使用 使用dll中的类 描述的方法如出一辙,只是Qt利用了其库的优势。 动态加载dll获取类在 《DLL的动态加载》 文章说已经说明,dll只可以导出函数,不可以导出指针,但是为了能得到dll中的类,可以导出一个接口,使用接口获取对象指针。但是在dll的调用一方,却无法识别获取到的类指针,所以利用C++的多态和继承的特性来完成。使用抽象类,声明好抽象接口,将需要导出的类继承自该抽象类,并实现其声明的接口。dll的导出方和调用方公用一个抽象类声明文件,在dll导出函数内部,利用多态,将抽象的类指针new成子类对象,并返回出来,则调用方就可以识别得到的类指针了。具体方法说明请参考文章《DLL的动态加载》 。 Qt的插件系统Qt的插件系统原理(这里只讨论High-Level API)与此相同,只是Qt利用了其内部非特性,使用QPluginLoader替代了导出类指针的接口,并使用宏定义进行导入和导出,避免了在导出导出上因为为了兼容C语言而导致的一些问题,并简化了一些操作。 使用方法既然原理相同,则需要的文件也相同,需要导出的dll文件和抽象类的声明文件。不同点是,不需要在使用C风格的函数导出类指针了,Qt里面使用宏定义替代。 步骤:
示例代码:插件项目plugin:HEADERS+= \plugin.h SOURCES+= \ plugin.cpp QT+=widgets DISTFILES+= \ plugin.json CONFIG+=plugin #表示用于lib模板:库是一个插件 TEMPLATE=lib #表示生成库文件 //plugin.h classPlugin : publicQObject, publicPluginInterface { Q_OBJECT Q_PLUGIN_METADATA(IIDpluginInterface_iidFILE"plugin.json") Q_INTERFACES(PluginInterface) public: explicitPlugin(QObject*parent=0); ~Plugin(); voidSayHello(QWidget*parent) Q_DECL_OVERRIDE; }; 说明:
Plugin::Plugin(QObject*parent) : QObject(parent) { qDebug()<<"constructor"; } Plugin::~Plugin() { qDebug()<<"destructor"; } voidPlugin::SayHello(QWidget*parent) { QMessageBox::information(parent, "plugin", "hello, this is dynamically loaded."); } { "Keys" : [ "plugin" ] } 调用项目test:插件生成的dll文件copy到执行目录下,共调用方加载 //interface.h classPluginInterface { public: virtual~PluginInterface(){} virtualvoidSayHello(QWidget*parent) =0; }; #define pluginInterface_iid "io.qt.dynamicplugin" Q_DECLARE_INTERFACE(PluginInterface, pluginInterface_iid) 说明:
PluginInterface*interface=NULL; QPluginLoaderplugin_loader("plugin.dll"); QObject*plugin=plugin_loader.instance(); if(plugin) { interface=qobject_cast<PluginInterface*>(plugin); if(interface) { interface->SayHello(this); } //delete plugin; plugin_loader.unload(); } 注:Qt文档中说明,QPluginLoader 释放之后,其获取到的插件不会释放,所以,需要手动 delete 插件,或者使用 unload() 方法释放。 ---------------------------------------------------------------------------------------------------------------------- 我们尊重原创,也注重分享,文章来源于微信公众号:Sherlock的程序人生,建议关注公众号查看原文。如若侵权请联系qter@qter.org。 ---------------------------------------------------------------------------------------------------------------------- |