IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> QT插件加载与相关宏定义 -> 正文阅读

[C++知识库]QT插件加载与相关宏定义

1.?应用程序与插件加载

对于QT应用程序来讲,一个插件就是一个类的实例。插件的可用的方法由对应的接口类来决定。接口类仅仅包含纯虚函数,也就是说接口并不实现任何方法函数。插件通过继承QObject且继承对应的接口类来实现内部的具体函数功能。当应用程序用QPLuginLoader类加载可能的插件时,就会得到一个指向QObject的指针。通过将这个对象用qobject_cast 强制封装成接口类,应用程序就会分辨出插件是否真正实现了期望的接口,如果是就被加载成正确的插件。

要让QPluginLoader正确工作需要两个条件:1.插件接口类需要用宏Q_DECLARE_INTERFACE来声明;2.插件类本身也需要用Q_INTERFACES宏来声明表示实现了接口。这两个宏能够安全地让插件类与插件接口类匹配。事实上,QT在加载插件时有一个如下的检测标准,如果不满足,插件就不能正确加载。检查标准列表:

  1. 构件插件与应用程序的Qt版本必须一致,也就是major与minor数字一样;
  2. 构件插件与应用程序必须在同一个平台,同一操作系统,同一编译器中构建;
  3. Qt库配置选项在插件与应用程序中一样,且以共享模式编译。
    1. Q_DECLARE_INTERFACE接口类声明

比如,我们已经定义了AddInInterfaceBase接口类,可以如下声明接口类,

Q_DECLARE_INTERFACE(AddInInterfaceBase, AddInInterface_CurrentVersion)

该宏定义在qobject.h中,其实就是定义了3个模板内联函数,展开如下,

# define Q_DECLARE_INTERFACE(IFace, IId) \

??? template <> inline const char *qobject_interface_iid<IFace *>() \

??? { return IId; } \

??? template <> inline IFace *qobject_cast<IFace *>(QObject *object) \

??? { return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : nullptr)); } \

??? template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \

??? { return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : nullptr)); }

#endif

2.Q_INTERFACES插件实现接口声明

Q_INTERFACE宏定义在qobjectdef.h中

#define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x)

进一步解析QT_ANNOTATE_CLASS,找到如下宏定义,

#ifndef QT_ANNOTATE_CLASS

# ifndef Q_COMPILER_VARIADIC_MACROS

#? define QT_ANNOTATE_CLASS(type, x)

# else

#? define QT_ANNOTATE_CLASS(type, ...)

# endif

#endif

这里可以看到只是一个空的定义,所以在源码中没有实际意义。主要用于MOC的输入,MOC会为Q_INTERFACES动态生成一些代码,确保qobject_cast()能正确进行QObject*到接口指针的转换,下面实例中详细讲述。

3. Q_PLUGIN_METADATA插件元数据宏

#define Q_PLUGIN_METADATA(x) QT_ANNOTATE_CLASS(qt_plugin_metadata, x)

与Q_INTERFACES类似,在代码层面也是空的,也用于MOC的输入,让MOC来动态生成一些代码。实际上,Q_PLUGIN_METADATA让MOC生成导出函数qt_plugin_instance(),供QPluginLoader()调用,创建接口实例,返回QObject的指针,在下面实例中详述。

4.MOC与Q_INTERFACES\Q_PLUG_METADATA的关系

Qt的插件机制是建立在元对象系统之上,所以要看一下Moc与Q_INTERFACES\Q_PLUGIN_METADATA两个宏之间的关系。

以OpenCVGrabber插件为例,

?

Q_PLUGIN_METADATA宏在自动生成的Moc文件中有IID与ClassName的信息,如下图,

?

查看一下,QT_MOC_EXPORT_PLUGIN的宏定义,

# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \

??????????? Q_EXTERN_C Q_DECL_EXPORT \

??????????? const char *qt_plugin_query_metadata() \

??????????? { return reinterpret_cast<const char *>(qt_pluginMetaData); } \

??????????? Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \

??????????? Q_PLUGIN_INSTANCE(PLUGINCLASS)

其中,Q_PLUGIN_INSTANCE,就是返回一个实例

#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \

??????? { \

??????????? static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \

??????????? if (!_instance) {??? \

??????????????? QT_PLUGIN_RESOURCE_INIT \

??????????????? _instance = new IMPLEMENTATION; \

??????????? } \

??????????? return _instance; \

????? ??}

Q_INTERFACES展开moc文件看到如下自动生成代码,

?

总结如下,

  1. Q_INTERFACES,确保能够正确类型转换;
  2. Q_PLUGIN_METADATA,生成插件元数据且生成qt_plugin_instance,供QPluginLoader使用;

5.QT插件加载器QPluginLoader

首先,看看它的声明比较简单

?

里面的instance返回对象实例指针,load()加载插件。上面声明中,有QJsonObject的定义来描述元数据,下面简单看一下元数据的描述格式Json

6. Json与插件元数据

Json是一种存储结构化数据的一种格式,概念中与xml类似,有6中基本数据类型:

Bool, double, string, array, object与null.

Json在插件中主要存储插件的元数据信息,在Qt中有一个专门的类QJsonObject对Json描述,与下表中其他配套的类一起来对Json管理。

类名

功能(中文)

QJsonArray

封装Json数组

QJsonDocument

读写Json文本

QJsonObject

封装Json对象

QJsonObject::iterator

Json迭代器

QJsonObject::const_iterator

Json常迭代器

QJsonParseError

报告Json解析错误

QJsonValue

封装Json值

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 15:59:31  更:2022-04-06 16:00:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:50:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码