【Qt】插件Plugin入门之Q_PLUGIN_METADATA()宏【2023.05.07】

这篇具有很好参考价值的文章主要介绍了【Qt】插件Plugin入门之Q_PLUGIN_METADATA()宏【2023.05.07】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

第一篇 插件Plugin入门之Q_PLUGIN_METADATA()宏

第二篇 插件Plugin入门之Q_PLUGIN_METADATA、Q_INTERFACE、Q_DECLARE_INTERFACE的功能剖析

第三篇:插件Plugin简明使用教程,未完


摘要

  分析Q_PLUGIN_METADATA宏的设计意图,站在设计者的意图进行插件的高屋建瓴式学习。

Meta-Object Compiler 简称MOC

  Qt 的 Meta-Object Compiler(MOC)是一个预处理器,用于处理带有特殊关键字的 C ++ 文件,并生成用于 Qt 的元对象代码。这是因为 Qt 提供了信号和槽机制,允许对象之间的通信。为了实现这一点,Qt 通过在每个QObject衍生类上创建一个“元对象”来动态识别其成员函数和其它属性,例如它们是否是信号或槽。

  MOC 是 Qt 的一部分,在安装 Qt 的时候会安装。在 Qt 的开发中,当 .h 文件中的 QObject 衍生类含有 Q_OBJECT 宏时,必须通过 MOC 来进行预处理,生成额外的元数据。

  MOC 的工作方式是扫描包含 Q_OBJECT 宏的 .h 文件,创建元数据并生成对应的 C++ 代码。此后,开发人员将使用 C++ 代码连接此元数据,以便在代码中使用信号和槽的机制。

Q_PLUGIN_METADATA宏的作用

  Qt插件是把一组功能进行封装,以静态库和动态库的形式提供给程序调用。在学习Qt之前,我已经知道了C++动态库就是把功能封装,通过导出函数的方式供调用者调用。C++动态库是通过dllexport关键字,告诉编译器把函数或类进行导出,动态库只有被导出的函数才能被调用方(外部)找到。

  Qt插件是在C++动态库基础之上进行的扩展,支持了信号-槽等新特性。Qt插件也需要告诉MOC导出了哪些函数、类。Qt中通过宏Q_PLUGIN_METADATA告诉MOC,哪个类被导出,也就是哪个类供外部调用。

*.h *.cpp文件、Q_PLUGIN_METADATA宏、MOC的关系图

【Qt】插件Plugin入门之Q_PLUGIN_METADATA()宏【2023.05.07】

上代码

  分析这个Q_PLUGIN_METADATA宏会使得MOC生成了哪些代码。先看下面的头文件。IID是给插件导处的类起个唯一的名字(字符串的形式),底层是个GUID。FILE是给插件属性信息指定个配置文件,暂时没用到先不管。

#ifndef ACCESSIBLEPLUGIN_H
#define ACCESSIBLEPLUGIN_H

#include <QAccessiblePlugin>

class AccessiblePlugin : public QAccessiblePlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QAccessibleFactoryInterface" FILE "simplePlugin.json")

public:
    explicit AccessiblePlugin(QObject *parent = nullptr);

private:
    QAccessibleInterface *create(const QString &key, QObject *object) override;
};

#endif // ACCESSIBLEPLUGIN_H

  我们看下编译后生成了些啥😱。如下是MOC编译出的 moc_accessibleplugin.cpp 文件。


/****************************************************************************
** Meta object code from reading C++ file 'accessibleplugin.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.9.9)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/

#include "../../simplePlugin/accessibleplugin.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qplugin.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'accessibleplugin.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
#error "This file was generated using the moc from 5.9.9. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif

QT_BEGIN_MOC_NAMESPACE
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
struct qt_meta_stringdata_AccessiblePlugin_t {
    QByteArrayData data[1];
    char stringdata0[17];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
    Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
    qptrdiff(offsetof(qt_meta_stringdata_AccessiblePlugin_t, stringdata0) + ofs \
        - idx * sizeof(QByteArrayData)) \
    )
static const qt_meta_stringdata_AccessiblePlugin_t qt_meta_stringdata_AccessiblePlugin = {
    {
QT_MOC_LITERAL(0, 0, 16) // "AccessiblePlugin"

    },
    "AccessiblePlugin"
};
#undef QT_MOC_LITERAL

static const uint qt_meta_data_AccessiblePlugin[] = {

 // content:
       7,       // revision
       0,       // classname
       0,    0, // classinfo
       0,    0, // methods
       0,    0, // properties
       0,    0, // enums/sets
       0,    0, // constructors
       0,       // flags
       0,       // signalCount

       0        // eod
};

void AccessiblePlugin::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
    Q_UNUSED(_o);
    Q_UNUSED(_id);
    Q_UNUSED(_c);
    Q_UNUSED(_a);
}

const QMetaObject AccessiblePlugin::staticMetaObject = {
    { &QAccessiblePlugin::staticMetaObject, qt_meta_stringdata_AccessiblePlugin.data,
      qt_meta_data_AccessiblePlugin,  qt_static_metacall, nullptr, nullptr}
};


const QMetaObject *AccessiblePlugin::metaObject() const
{
    return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}

void *AccessiblePlugin::qt_metacast(const char *_clname)
{
    if (!_clname) return nullptr;
    if (!strcmp(_clname, qt_meta_stringdata_AccessiblePlugin.stringdata0))
        return static_cast<void*>(this);
    return QAccessiblePlugin::qt_metacast(_clname);
}

int AccessiblePlugin::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QAccessiblePlugin::qt_metacall(_c, _id, _a);
    return _id;
}

QT_PLUGIN_METADATA_SECTION const uint qt_section_alignment_dummy = 42;

#ifdef QT_NO_DEBUG

QT_PLUGIN_METADATA_SECTION
static const unsigned char qt_pluginMetaData[] = {
    'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', ' ',
    'q',  'b',  'j',  's',  0x01, 0x00, 0x00, 0x00,
    0xd4, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
    0xc0, 0x00, 0x00, 0x00, 0x1b, 0x03, 0x00, 0x00,
    0x03, 0x00, 'I',  'I',  'D',  0x00, 0x00, 0x00,
    '-',  0x00, 'o',  'r',  'g',  '.',  'q',  't', 
    '-',  'p',  'r',  'o',  'j',  'e',  'c',  't', 
    '.',  'Q',  't',  '.',  'Q',  'A',  'c',  'c', 
    'e',  's',  's',  'i',  'b',  'l',  'e',  'F', 
    'a',  'c',  't',  'o',  'r',  'y',  'I',  'n', 
    't',  'e',  'r',  'f',  'a',  'c',  'e',  0x00,
    0x1b, 0x0b, 0x00, 0x00, 0x09, 0x00, 'c',  'l', 
    'a',  's',  's',  'N',  'a',  'm',  'e',  0x00,
    0x10, 0x00, 'A',  'c',  'c',  'e',  's',  's', 
    'i',  'b',  'l',  'e',  'P',  'l',  'u',  'g', 
    'i',  'n',  0x00, 0x00, ':',  '!',  0xa1, 0x00,
    0x07, 0x00, 'v',  'e',  'r',  's',  'i',  'o', 
    'n',  0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
    0x05, 0x00, 'd',  'e',  'b',  'u',  'g',  0x00,
    0x15, 0x13, 0x00, 0x00, 0x08, 0x00, 'M',  'e', 
    't',  'a',  'D',  'a',  't',  'a',  0x00, 0x00,
    '(',  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
    '$',  0x00, 0x00, 0x00, 0x14, 0x03, 0x00, 0x00,
    0x04, 0x00, 'K',  'e',  'y',  's',  0x00, 0x00,
    0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
    0x0c, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
    'H',  0x00, 0x00, 0x00, '|',  0x00, 0x00, 0x00,
    'l',  0x00, 0x00, 0x00
};

#else // QT_NO_DEBUG

QT_PLUGIN_METADATA_SECTION
static const unsigned char qt_pluginMetaData[] = {
    'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', ' ',
    'q',  'b',  'j',  's',  0x01, 0x00, 0x00, 0x00,
    0xd4, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
    0xc0, 0x00, 0x00, 0x00, 0x1b, 0x03, 0x00, 0x00,
    0x03, 0x00, 'I',  'I',  'D',  0x00, 0x00, 0x00,
    '-',  0x00, 'o',  'r',  'g',  '.',  'q',  't', 
    '-',  'p',  'r',  'o',  'j',  'e',  'c',  't', 
    '.',  'Q',  't',  '.',  'Q',  'A',  'c',  'c', 
    'e',  's',  's',  'i',  'b',  'l',  'e',  'F', 
    'a',  'c',  't',  'o',  'r',  'y',  'I',  'n', 
    't',  'e',  'r',  'f',  'a',  'c',  'e',  0x00,
    0x15, 0x0b, 0x00, 0x00, 0x08, 0x00, 'M',  'e', 
    't',  'a',  'D',  'a',  't',  'a',  0x00, 0x00,
    '(',  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
    '$',  0x00, 0x00, 0x00, 0x14, 0x03, 0x00, 0x00,
    0x04, 0x00, 'K',  'e',  'y',  's',  0x00, 0x00,
    0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
    0x1b, 0x12, 0x00, 0x00, 0x09, 0x00, 'c',  'l', 
    'a',  's',  's',  'N',  'a',  'm',  'e',  0x00,
    0x10, 0x00, 'A',  'c',  'c',  'e',  's',  's', 
    'i',  'b',  'l',  'e',  'P',  'l',  'u',  'g', 
    'i',  'n',  0x00, 0x00, '1',  0x00, 0x00, 0x00,
    0x05, 0x00, 'd',  'e',  'b',  'u',  'g',  0x00,
    ':',  '!',  0xa1, 0x00, 0x07, 0x00, 'v',  'e', 
    'r',  's',  'i',  'o',  'n',  0x00, 0x00, 0x00,
    0x0c, 0x00, 0x00, 0x00, 'H',  0x00, 0x00, 0x00,
    0x80, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
    0xb0, 0x00, 0x00, 0x00
};
#endif // QT_NO_DEBUG

QT_MOC_EXPORT_PLUGIN(AccessiblePlugin, AccessiblePlugin)

QT_WARNING_POP
QT_END_MOC_NAMESPACE


🍖最大的块头static const unsigned char qt_pluginMetaData[] = {}; 这是一个字符串数组,里面存储的插件的信息。整理下排版如下:

//非Debug版
QTMETADATA  qbjs1   d4   b   c0   1b3  3 
IID   - org.qt-project.Qt.QAccessibleFactoryInterface 1bb  9 
className 10 AccessiblePlugin  :!a1 7 
version   11   5 
debug 1513  8 
MetaData  (   3   $   143  4 Keys  c           c   c   88   H   |   l



//Debug版
QTMETADATA  qbjs1   d4   b   c0   1b3  3 
IID   - org.qt-project.Qt.QAccessibleFactoryInterface 15b  8 
MetaData  **********
className 10 AccessiblePlugin  31   5 
debug :!a1 7 
version   c   H   80   a4   b0

这两个版本都有IID信息和className。IID字符串和宏里面定义的字符串是一样的,记住IID是导出类的身份ID。className 就是我们插件导出的类名。


回到Q_PLUGIN_METADATA宏的作用

  上文分析了宏对moc文件的影响,最明显的是这个宏影响了moc文件的字符数组qt_pluginMetaData的值。Qt的MOC通过这个字符数组知道插件的导出类名、IID的值等信息。正如我们通过dllexport函数告诉C++编译器,要导出某个类一样,只不过这个宏是告诉Qt的MOC要导出的类。

// 进一步的分析需要对MOC、 META-DATA、 QObject、 d指针有深入的剖析。文章来源地址https://www.toymoban.com/news/detail-436270.html

到了这里,关于【Qt】插件Plugin入门之Q_PLUGIN_METADATA()宏【2023.05.07】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SystemUI之插件Plugin

    一、为何要用插件plugin SystemUI模块非常多,结构自然也就非常复杂,而且SystemUI是一个常驻的进程,不能随意做修改升级,如果修改不到位,很可能会存在bug,这是修复就非常难。另外一个原因是可以方便客户客制化,如需要改变状态栏的背景色、显示时钟的风格、锁屏壁纸

    2024年03月20日
    浏览(38)
  • ElasticSearch插件plugin ik分词器,报错plugin-descriptor.properties

    @ES日志中报错plugin-descriptor.properties NoSuchFileException 找不到这个文件plugin-descriptor.properties。 ` 如下图所示,下载的zip文件解压之后的情况,这里是不能放到elasticsearch的plugins中的。 分析:由于是java开发的分词器,这里很明显是maven项目的目录结构。所以要执行打包命令,生成

    2024年02月11日
    浏览(38)
  • qt.qpa.plugin: Could not load the Qt platform plugin “xcb“

    在服务器远程运行会弹出窗口显示画面的代码时,可能遇到上述报错 首先执行`export QT_DEBUG_PLUGINS=1`,再运行一次导致报错的代码。可以看到详细错误信息,我这里看到具体错误为:  少了这样一个包,但是直接`apt-get update`,`apt-get install libxcb-icccm`是找不到的。此时应该执行

    2024年03月27日
    浏览(44)
  • qt.qpa.plugin:Could not load the Qt platform plugin “xcb“

    提示信息:  错误信息中提到“\\\"/home/zxq/anaconda3/envs/open3d/lib/python3.9/site-packages/cv2/qt/plugins”  解决办法1 :首先按照提示信息的建议“Reinstalling the application may fix this problem.”,卸载原来的opencv,一般都能解决。 解决办法2 :删除上面目录中的libqxcb.so文件即可 解决办法3 :尝

    2024年02月03日
    浏览(53)
  • 手写一个webpack插件(plugin)

    熟悉 vue 和 react 的小伙伴们都知道,在执行过程中会有各种生命周期钩子,其实webpack也不例外,在使用webpack的时候,我们有时候需要在 webpack 构建流程中引入自定义的行为,这个时候就可以在 hooks 钩子中添加自己的方法。 创建插件 webpack 加载 webpack.config.js 中所有配置,此

    2024年02月08日
    浏览(47)
  • qt.qpa.plugin: Could not load the Qt platform plugin “xcb“ in

    兄弟们看看是不是这个错: VScode 80年不出个错,今儿冒出来这个,我也不知道是mmdet配置问题,还是opencv-python的问题,还是VScode的问题hhhh 参考该链接: https://blog.csdn.net/LOVEmy134611/article/details/107212845 把QT的flag打开,我们才能看到报错的详细信息 注意,这个执行后,该环境变

    2024年02月09日
    浏览(45)
  • qt.qpa.plugin: Could not find the Qt platform plugin “windows“ in ““

    使用nuitka打包pyqt5后,运行exe时报错 报错如下: 原因分析 这是由于打包后,pyqt5无法找到插件plugin 导致的。 解决方法 1、先找到虚拟环境中的Pyqt5,比如我的: 2、把Qt5文件夹复制到打包好后的PyQt5文件夹中 亲测有效,如果能够解决你遇到的问题,请帮忙点个赞,顺便收藏下

    2024年02月15日
    浏览(57)
  • Chat Plugin插件清单(中文版)

    整理了一份插件清单,部分插件可能已下线,也可能不在列表中。除了这份清单外,还整理了一份:超级牛逼的学习指南 欢迎大家转发、收藏、点赞支持!谨防失联! 插件名称 功能 基本提示 高级提示 KeyMate.AI搜索 使用AI驱动的自定义搜索引擎查找网页 “搜索关于可再生能

    2024年02月08日
    浏览(41)
  • Webpack:HTML Webpack Plugin插件

            HTML Webpack Plugin 插件,在Webpack构建的前端项目中,用于简化index.html文件的创建,以免除项目打包之后手动创建/拷贝index.html到打包目录下的繁琐步骤。以下,从一个已构建好的Vue项目中的一个现象谈起,逐步深入了解此插件的使用。 目录 从Vue项目中的index.html谈起

    2024年02月07日
    浏览(41)
  • 关于qt.qpa.plugin: Could not find the Qt platform plugin “windows“ in ““问题的解决

    我再安装matplotlib使用的是anaconda直接安装的,这个包会自带一个QTdesigner,和我原先环境内的pyside2冲突。当我卸载matplotlib后就发生上述报错。 问题很简单,就是程序找不到plugin插件了 向环境变量里添加 这个方案在别的文章里很容易找到 但这个也会出现一个问题,就是自己电

    2024年02月08日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包