怎样开发 Qt 插件,能够在 Qt Assistant 中搜索 "Qt Plugins" 或 "How to Create Qt Plugins", 看看那篇 manual 中的介绍。
当中涉及到了几个宏
Q_DECLARE_INTERFACE(ClassName, Identifier)This macro associates the given Identifier (a string literal) to the interface class called ClassName. The Identifier must be unique.
This macro is normally used right after the class definition for ClassName, in a header file.
Q_INTERFACES(...)This macro tells Qt which interfaces the class implements. This is used when implementing plugins.
Q_PLUGIN_METADATA(...)This macro is being used to declare meta data that is part of a plugin that instantiates this object.
The macro needs to declare the IID of the interface implemented through the object, and reference a file containing the meta data for the plugin.
There should be exactly one occurrence of this macro in the source code for a Qt plugin.
当中,Q_PLUGIN_METADATA(...) 宏在前面讲 "Qt 插件的元信息" 的那篇文章中已经介绍过了,它基本是这些宏里最重要的一个。由于
MOC 会依据这个宏生成非常多跟该插件相关的东西,包含元信息、获取插件实例的函数等。可用它能够将插件导出,其作用类似于老版本号
Qt 中的 Q_EXPORT_PLUGIN2 宏
Q_DECLARE_INTERFACE 宏是与 qobject_cast 相关的,它为接口类定义了 qobject_interface_iid 和 qobject_cast 这两个模板
Qt 的源代码中给出了宏 Q_DECLARE_INTERFACE 的定义
- #define Q_DECLARE_INTERFACE(IFace, IId) template < >inline const char * qobject_interface_iid() {
- return IId;
- }
- template < >inline IFace * qobject_cast(QObject * object) {
- return reinterpret_cast((object ? object - >qt_metacast(IId) : 0));
- }\
- // qt_metacast通过插件的IID来映射接口类的指针。一个IID绑定一个接口类
- template < >inline IFace * qobject_cast(const QObject * object) {
- return reinterpret_cast((object ? const_cast < QObject * >(object) - >qt_metacast(IId) : 0));
- }
Q_INTERFACES 宏也是与 qobject_cast 相关,没有 Q_DECLARE_INTERFACE 和 Q_INTERFACES 这两个宏。就无法对从插件中获取的实例指针进行 qobject_cast 映射。
只是。Q_INTERFACES 宏并没有在 Qt 的源代码中定义。他是 MOC 的菜,MOC 会利用这个宏生成一些代码。要注意一点,假设一个头文件或源文件里用到了 Q_INTERFACES 宏,
那么在调用这个宏之前。必须存在一个 Q_DECLARE_INTERFACE 宏声明对应的接口(或者包括一个用 Q_DECLARE_INTERFACE 宏声明了该接口的头文件),MOC 会检查这一点,由于它在为 Q_INTERFACES 宏生成代码时要用到 Q_DECLARE_INTERFACE 宏的 IID 參数。
举例,
头文件 MyPluginInterface.h 中虚拟接口类的定义例如以下
- #include < QtPlugin > #define QtPluginDemo_iid "org.qt-project.Qt.PluginDemo" // 定义接口的IID
- class MyPluginInterface {
- public: virtual~MyPluginInterface() {}
- virtual void showPluginName();
- };
- Q_DECLARE_INTERFACE(MyPluginInterface, QtPluginDemo_iid);
头文件 MyPlugin.h 中类的定义例如以下
- class MyPlugin: public QObject,
- public MyPluginInterface {
- Q_OBJECT
- // Q_PLUGIN_METADATA ( IID QtPluginDemo_iid FILE "MyPlugin.json")
- Q_PLUGIN_METADATA(IID QtPluginDemo_iid) Q_INTERFACES(MyPluginInterface)
- public: void showPluginName();
- };
将头文件 MyPlugin.h 用 MOC 处理之后。生成的代码中有例如以下部分
(仅仅列出了 MOC 为 Q_INTERFACES 宏生成的代码,MOC 为 Q_PLUGIN_METADATA 宏生成的代码在前面讲 "Qt 插件的元信息" 的那篇文章中介绍过了):
- ......
- static const qt_meta_stringdata_MyPlugin_t qt_meta_stringdata_MyPlugin = {
- {
- QT_MOC_LITERAL(0, 0, 8)
- },
- "MyPlugin"
- };......
- void * MyPlugin: :qt_metacast(const char * _clname) // Q_DECLARE_INTERFACE宏就是利用这个函数实现的qobject_cast类型映射
- {
- if (!_clname) return 0;
- if (!strcmp(_clname, qt_meta_stringdata_MyPlugin.stringdata)) // 假设_clname与类的名称MyPlugin匹配,返回有效指针
- return static_cast < void * >(const_cast < MyPlugin * >(this));
- if (!strcmp(_clname, "MyPluginInterface")) // 假设_clname与接口类的名称MyPluginInterface匹配,返回有效指针
- return static_cast < MyPluginInterface * >(const_cast < MyPlugin * >(this));
- if (!strcmp(_clname, "org.qt-project.Qt.PluginDemo")) // 假设_clname与接口类的IID匹配,返回有效指针。
- // 这里就用到了调用Q_DECLARE_INTERFACE宏时使用的IID參数
- // 并且,Q_DECLARE_INTERFACE宏的代码中也是利用IID映射实现的qobject_cast
- return static_cast < MyPluginInterface * >(const_cast < MyPlugin * >(this));
- return QObject: :qt_metacast(_clname);
- }......
来源: http://www.bubuko.com/infodetail-2226198.html