Qt5的插件机制(4)--Qt插件的元信息metaData

Qt -- 输入法插件 Qt应用启动之前会根据环境变量QT_IM_MODULE的值加载匹配的输入法插件,此过程可简单理解为: Qt扫描QT_INSTALL/plugins/platforminputcontexts/路径下的.dll文件,并尝试加载 得到插件中实现了QPlatformInputContextPlugin类的实例 调用步骤2中实例的create方法,create的传入参数key为QT_IM_MODULE... 阅读详情

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

JSON 与Qt插件的元信息 MetaData


Qt插件的源码中,基本都能见到一个 xxx.json 的文件,这个文件中通常只包含一句:

{
    "Keys": [ "yyy" ]
}

我们可以猜到这个文件中的"Keys"应该是指定了与插件相关的关键字。那这个 .json 文件到底是如何起作用的?
先来认识一下 JSON .

JSON是一种存储结构化数据的格式,它有6中基本数据类型,分别是:

bool    布尔型,取值可以是 true 或 false
double    数字类型
string    字符串类型
array    数组类型
object    对象类型
null    空类型

具体可参见 Qt Assistant 中关于"JSON Support in Qt "的介绍。

A simple JSON document encoding a person, his/her age, address and phone numbers could look like:

{
    "FirstName": "John",    # FirstName是变量(字段)的名称;John是变量的值
    "LastName": "Doe",
    "Age": 43,
    "Address": {
        "Street": "Downing Street 10",
        "City": "London",
        "Country": "Great Britain"
    },
    "Phone numbers": [
        "+44 1234567",
        "+44 2345678"
    ]
}



值得一提的是,数组类型的字段在.json文件中赋值时应该用方括号 '[' 和 ']' 括起来,对象类型的字段在赋值时
应用花括号 '{' 和 '}' 括起来,普通类型的数据则不需要括。每一个 .json 文件描述了一个 JSON对象,而一个JSON
对象中的对象类型字段,又可以看做是一个子JSON对象(JSON对象的嵌套)。
再回过头来看看插件源码中的 xxx.json 文件,可以发现其中的变量 Keys 其实是个数组变量(因为它赋值时用方括号
括住了),只不过这个数组中通常只有一个元素而已,即一个插件一般只有一个关键字,当然也可以为一个插件设置多个
关键字。

.json在Qt插件中主要用于存储Qt插件的元信息(metaData),在Qt中,有一个专门的类 QJsonObject 来描述一个JSON。
QLibraryPrivate::metaData() 返回的是一个QJsonObject类的指针,通过这个指针可以访问该 QLibraryPrivate 对象对应的库的元信息;
QFactoryLoader::metaData() 返回的是一个 QList<QJsonObject> 列表,这个列表中顺序存放了与该 QFactoryLoader 对象相关的所有库
的元信息(动态库的元信息在前,静态库的元信息在后)。
另外值得注意的是,QLibraryPrivate::metaData() 返回的QJsonObject对象中一般都有一个 MetaData 字段,这个字段是对象类型的数据,
他可以看做是库的元信息的一个子JSON对象,而且它对应的就是 .json 文件中的内容。(.json文件中的内容只是一个库的元信息的一部分)

每个QFactoryLoader对象都有一个 d->iid 成员 (d是与QFactoryLoader对象关联的QFactoryLoaderPrivate实例),可用于描述插件的种类,
每一类插件都有一个独立的 IID 值, 比如平台输入法类插件的IDD都应该是 org.qt-project.Qt.QPlatformInputContextFactoryInterface,
平台类插件的IDD都应是 org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2 等。



<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

QLibraryPrivate的metaData(库的元信息)的产生过程



在编写Qt插件时需要用到 Q_PLUGIN_METADATA 这个宏来设置一个插件的元信息,但在Qt的源码中,发现这个宏是空的,所以不用说,这个
宏是被MOC解析的而不是C++编译器。那就看看MOC会怎么对付这个宏吧。找了个很简单的文件,用moc处理一下,看看都生成了什么。

main.cpp文件内容如下,其中使用了Q_PLUGIN_METADATA宏


#include <qpa/qplatforminputcontextplugin_p.h>
#include <QtCore/QStringList>
#include "QtMinimalInputMethodFrame.h"
QT_BEGIN_NAMESPACE
class QtMinimalInputMethodFramePlugin : public QPlatformInputContextPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPlatformInputContextFactoryInterface" FILE "qtminimal.json")    // 指定了IID和.json文件

public:
    QtMinimalInputMethodFrame *create(const QString &, const QStringList &);
};
QtMinimalInputMethodFrame *QtMinimalInputMethodFramePlugin::create(const QString &system, const QStringList ¶mList)
{
    Q_UNUSED(paramList);
    if (system.compare(system, QStringLiteral("qtminimal"), Qt::CaseInsensitive) == 0)
        return new QtMinimalInputMethodFrame;
    return 0;
}
QT_END_NAMESPACE
#include "main.moc"



qtminimal.json文件内容如下:

{
    "Keys": [ "qtminimal" ]
}

使用 "moc main.cpp moc_main.cpp" ,生成moc_main.cpp文件,打开,发现里面有一部分代码如下:

    ...
    ...

static const unsigned char qt_pluginMetaData[] = {
    'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', ' ',        // "QTMETADATA",这段字符串可看做Qt的插件元信息的头,通过这个关键字能搜索到元信息的位置
    0x71, 0x62, 0x6a, 0x73, 0x01, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
    0xec, 0x00, 0x00, 0x00, 0x1b, 0x03, 0x00, 0x00,
    0x03, 0x00, 0x49, 0x49, 0x44, 0x00, 0x00, 0x00,
    0x37, 0x00, 0x6f, 0x72, 0x67, 0x2e, 0x71, 0x74,
    0x2d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
    0x2e, 0x51, 0x74, 0x2e, 0x51, 0x50, 0x6c, 0x61,
    0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6e, 0x70,
    0x75, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78,
    0x74, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79,
    0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63,
    0x65, 0x00, 0x00, 0x00, 0x9b, 0x0c, 0x00, 0x00,
    0x09, 0x00, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e,
    0x61, 0x6d, 0x65, 0x00, 0x1f, 0x00, 0x51, 0x74,
    0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x49,
    0x6e, 0x70, 0x75, 0x74, 0x4d, 0x65, 0x74, 0x68,
    0x6f, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x50,
    0x6c, 0x75, 0x67, 0x69, 0x6e, 0x00, 0x00, 0x00,
    0x5a, 0x60, 0xa0, 0x00, 0x07, 0x00, 0x76, 0x65,
    0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00,
    0x11, 0x00, 0x00, 0x00, 0x05, 0x00, 0x64, 0x65,
    0x62, 0x75, 0x67, 0x00, 0x95, 0x16, 0x00, 0x00,
    0x08, 0x00, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61,
    0x74, 0x61, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
    0x03, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
    0x14, 0x03, 0x00, 0x00, 0x04, 0x00, 0x4b, 0x65,
    0x79, 0x73, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
    0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
    0x09, 0x00, 0x71, 0x74, 0x6d, 0x69, 0x6e, 0x69,
    0x6d, 0x61, 0x6c, 0x00, 0x8b, 0x01, 0x00, 0x00,
    0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
    0xa4, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
    0x98, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00
};
    ...
    ...

// 留意一下QT_MOC_EXPORT_PLUGIN这个宏
QT_MOC_EXPORT_PLUGIN(QtMinimalInputMethodFramePlugin, QtMinimalInputMethodFramePlugin)    

    ...
    ...



上面的代码中生成了一个名为 qt_pluginMetaData 的数组,看其名字就能猜出来这个数组是与插件的元信息有关的,
将该数组用字符显示,结果为:
QTMETADATA  qbjs^A^@^@^@^@^A^@^@^K^@^@^@ì^@^@^@^[^C^@^@^C^@
IID^@^@^@7^@org.qt-project.Qt.QPlatformInputContextFactoryInterface    // IDD
^@^@^@<9b>^L^@^@^@        
className^@^_^@QtMinimalInputMethodFramePlugin        // 类名
^@^@^@Z` ^@^G^@
version^@^@^@^Q^@^@^@^E^@            // 版本
debug^@<95>^V^@^@^H^@                // debug
MetaData^@^@8^@^@^@^C^@^@^@4^@^@^@^T^C^@^@^D^@    // MetaData
Keys^@^@^\^@^@^@^B^@^@^@^X^@^@^@^@qtminimal    // Keys
^@<8b>^A^@^@^L^@^@^@^L^@^@^@¤^@^@^@T^@^@^@<98>^@^@^@<88>^@^@^@


可以看到其中已经包含了IDD、Keys等信息,因此可以确定与插件相关的元信息就是存在这个数组中。
上面给出的代码最后,使用了QT_MOC_EXPORT_PLUGIN宏,它的作用是定义两个函数,qt_plugin_instance() 和
qt_plugin_query_metadata(),前者用于返回插件类(QtMinimalInputMethodFramePlugin)的一个实例,后者用于
返回数组qt_pluginMetaData的指针。因此,当这个库被加载后,通过库中的qt_plugin_query_metadata()函数就可以获得
库的元信息数组(二进制数据)。

#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \    // 这个宏用于返回一个类名是IMPLEMENTATION的类的静态实例
        { \
            static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \
            if (!_instance)      \
                _instance = new IMPLEMENTATION; \
            return _instance; \
        }

#if defined(QT_STATICPLUGIN)
    // 这部分是静态编译时用的宏,我们暂不管它
#  define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
    static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \
    Q_PLUGIN_INSTANCE(PLUGINCLASS) \
    static const char *qt_plugin_query_metadata_##PLUGINCLASSNAME() { return (const char *)qt_pluginMetaData; } \
    const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASSNAME() { \
        QT_PREPEND_NAMESPACE(QStaticPlugin) plugin = { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \
        return plugin; \
    }

#else
    // 这部分才是动态编译时用的宏
#  define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME)      \
            Q_EXTERN_C Q_DECL_EXPORT \
            const char *qt_plugin_query_metadata() \            // 这个函数返回一个指针,指向元信息数组
            { return (const char *)qt_pluginMetaData; } \
            Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \ 这个函数返回插件类PLUGINCLASS的一个静态实例
            Q_PLUGIN_INSTANCE(PLUGINCLASS)

#endif


我们虽然可以通过qt_plugin_query_metadata()函数获得库的元信息数组(二进制数据),但是还需要把这些
二进制数据转换成 QJsonObject 对象,这样才方便在程序中对其各个字段进行访问。QLibraryPrivate类有个
静态成员函数fromRawMetaData,可以从二进制数据中构造一个 QJsonDocument 对象,
而QJsonDocument对象的 object() 方法就能返回所需的 QJsonObject 对象(库的元信息)。
通过这些可以猜测,QLibraryPrivate类的 metaData 成员是这样被设置的:
加载一个库文件后,将库中的qt_plugin_query_metadata()这个符号resolve出来,并通过它得到数组 qt_pluginMetaData 的指针,
然后调用QLibraryPrivate类的fromRawMetaData方法讲二进制存储的元信息转换到一个QJsonObject 对象中,最后将这个对象赋值
给QLibraryPrivate类的metaData成员。


现在问题是, QLibraryPrivate的metaData是在哪里,被谁设置的?

当第一次使用 QLibraryPrivate类的 isPlugin() 方法调查一个库是否是插件时,这个方法内部会调用 QLibraryPrivate::updatePluginState() 。

bool QLibraryPrivate::isPlugin()
{
    if (pluginState == MightBeAPlugin)    // pluginState在构造函数中会被初始化为MightBeAPlugin
        updatePluginState();

    return pluginState == IsAPlugin;
}

而QLibraryPrivate::updatePluginState()函数中,需要读取QLibraryPrivate类的 metaData 信息来确认一个库是不是插件,而 metaData 也就是在这时
被设置的。从这个函数中还可以看出,只有Qt插件才有 metaData 元信息, 普通的库是没有的(这一点我上不能打保票,不过从下面这个函数的代码上看,应该
是这样的)。

void QLibraryPrivate::updatePluginState()
{
    errorString.clear();
    if (pluginState != MightBeAPlugin)
        return;        // 如果pluginState的状态已经确定了,则直接返回

    bool success = false;

#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
    if (fileName.endsWith(QLatin1String(".debug"))) {
        // refuse to load a file that ends in .debug
        // these are the debug symbols from the libraries
        // the problem is that they are valid shared library files
        // and dlopen is known to crash while opening them

        // pretend we didn't see the file
        errorString = QLibrary::tr("The shared library was not found.");
        pluginState = IsNotAPlugin;
        return;
    }
#endif

    // 这里开始设置 metaData 。findPatternUnloaded() 和 qt_get_metadata() 两个函数的内部都会设置 metaData
    if (!pHnd) {
    // 如果库还没有被加载,(pHnd==NULL说明库未被加载),则调用findPatternUnloaded函数,它内部会
    // 讲对应的库文件打开,读取其内容,在其中寻找Qt的插件元信息的头Header(就是前面提到的"QTMETADATA"),
    // 如果找到了,就解析元信息。这种方法的好处是在不加载库的情况下也能获得其元信息。
        // scan for the plugin metadata without loading
        success = findPatternUnloaded(fileName, this);    
    } else {
    // 如果库已被加载,则调用qt_get_metadata获得元信息。
    // QtPluginQueryVerificationDataFunction是一个函数指针类型,其具体类型是 :  char*(*)(), 它返回
    // 一个字符指针(指向一个二进制数组),准确的说,他应该返回上面提到的qt_pluginMetaData数组的指针 。

        // library is already loaded (probably via QLibrary)
        // simply get the target function and call it.
        QtPluginQueryVerificationDataFunction getMetaData = NULL;
        getMetaData = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_metadata");    
        // 上面这行将库中的qt_plugin_query_metadata符号resolve出来
        success = qt_get_metadata(getMetaData, this);
    }

    if (!success) {
    // 如果获取 元信息 失败,即当前库没有元信息,就将pluginState设置为IsNotAPlugin,代表非Qt插件。
    // 这里因为当前库没有元信息,就认为它不是Qt插件,所以这是不是意味着,只有Qt插件才有元信息而普通库是没有的?
        if (errorString.isEmpty()){
            if (fileName.isEmpty())
                errorString = QLibrary::tr("The shared library was not found.");
            else
                errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName);
        }
        pluginState = IsNotAPlugin;
        return;
    }

    pluginState = IsNotAPlugin; // be pessimistic

    // 如果获取 元信息 成功,再看版本号是否符合要求,如果版本号合适,则将pluginState设置为IsAPlugin,代表是Qt插件
    uint qt_version = (uint)metaData.value(QLatin1String("version")).toDouble();
    bool debug = metaData.value(QLatin1String("debug")).toBool();
    if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) {
        if (qt_debug_component()) {
            qWarning("In %s:\n"
                 "  Plugin uses incompatible Qt library (%d.%d.%d) [%s]",
                 (const char*) QFile::encodeName(fileName),
                 (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff,
                 debug ? "debug" : "release");
        }
        errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]")
            .arg(fileName)
            .arg((qt_version&0xff0000) >> 16)
            .arg((qt_version&0xff00) >> 8)
            .arg(qt_version&0xff)
            .arg(debug ? QLatin1String("debug") : QLatin1String("release"));
#ifndef QT_NO_DEBUG_PLUGIN_CHECK
    } else if(debug != QLIBRARY_AS_DEBUG) {
        //don't issue a qWarning since we will hopefully find a non-debug? --Sam
        errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
                 " (Cannot mix debug and release libraries.)").arg(fileName);
#endif
    } else {
        pluginState = IsAPlugin;
    }
}






【Qt】【插件Plugin 篇一】 入门之Q_PLUGIN_METADATA()宏【2023.05.07】 分析Q_PLUGIN_METADATA宏的设计意图,站在设计者的意图进行插件的高屋建瓴式学习。与dllexport进行对比学习。 阅读详情

相关推荐

Qt插件机制demo示例

项目结构架构解读上面这张图把 Qt 插件机制拆成了编译期 (灰线):宿主和插件都`#include` 同一份,但各自独立编译。宿主完全不知道。这就是插件机制能做到""的根本原因。运行时 ():用户点击"加载插件"后, mainwindow.cpp 里的`QPluginLoader` 把磁盘上的`helloworld.dll`,调用`instance()` 实例化对象,再用`` 验证它确实实现了这个接口。

weixin_51883798的博客 237

Qt-插件机制

1 qt插件的使用 参考:【QT】QT中插件化开发及其简单使用_bailang_zhizun的博客-优快云博客_qt插件开发 代码:qt插件的简单使用,插件创建,和使用-Flutter文档类资源-优快云下载 2 剖析 QT插件程序开发流程 编写扩展 Qt 应用程序的插件,步骤如下: (1)、声明一个继承自 QObject 和插件想要提供的接口的插件类 (2)、使用 Q_INTERFACES() 宏来告诉 Qt 元对象系统有关接口的情况 (3)、使用 Q_PLUGIN_M..

LIJIWEI0611的博客 4687

qt5虚拟键盘 QPlatformInputContext

qt5虚拟键盘,继承于QPlatformInputContext类,实现了简单的输入法。 点击qt5的inputbox可以弹出虚拟键盘,Windows和Linux下均实验成功。

Q_PLUGIN_METADATA Q_INTERFACE Q_DECLARE_INTERFACE qt_pluginMetaData

Q_PLUGIN_METADATA Q_DECALER_INTERFACE Q_INTERFACE QT_MOC_EXPORT_PLUGIN qt_plugin_instance

qiushangren的专栏 2724

【STM32-DSP库的使用】基于Keil5 + STM32CubeMX + CMSIS-DSP 手动添加、库添加方式

CMSIS-DSP库在工程中应用遇到的所有问题进行归纳终结

洋洋的博客 1万+

飞控芯片的隐形战场:传感器冗余与实时OS的可靠性革命

本文深入探讨飞控芯片在工业级无人机中的可靠性设计,聚焦传感器冗余架构与实时操作系统(RTOS)的容错机制。通过多IMU备份、自适应加权融合算法及NuttX、ChibiOS等RTOS的故障隔离技术,确保系统在极端环境下毫秒级自愈。文章还涵盖开源生态如PX4的跨平台移植及RISC-V架构的应用,为高可靠性飞控系统提供关键技术参考。

z5a6b的博客 877

qt插件元数据不包含一个有效的元数据_Qt5该插件机制(4)--QtMeta信息窗口小部件metaData...

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<...

weixin_39841640的博客 452

博图HMI多语言文本列表一键生成攻略:从Excel模板到TIA Portal的完整流程

本文详细介绍了如何利用Excel模板和TIA Portal API实现博图HMI多语言文本列表的一键生成。通过标准化Excel模板设计、解析TIA Portal的XML结构,并结合C#代码实现自动化导入,大幅提升多语言项目的开发效率。特别适用于需要支持多语言版本的自动化设备HMI界面开发。

weixin_26934905的博客 218

Q_PLUGIN_METADATA 宏在 Qt 插件开发中用于声明和提供插件的元数据(metadata),使得 Qt 的插件机制能够识别并正确加载该插件

宏在 Qt 插件开发中用于声明和提供插件的元数据(metadata),使得 Qt 的插件机制能够识别并正确加载该插件。它的使用是构建 Qt 插件的重要步骤之一,通常与Q_OBJECT和一起使用。

m0_46376834的博客 1350

生成式引擎优化(GEO)- 搜索引擎优化

生成式引擎优化(GEO)是针对AI内容生成平台(如ChatGPT)的新型优化策略,旨在提升品牌内容在AI生成答案中的引用率,与传统SEO存在显著差异。GEO通过优化内容权威性、结构化和语义关联,适应AI的RAG技术架构,采用3C原则(可爬性、网络共识、反馈校正)提升内容可见性。其核心区别在于目标(引用率vs排名)、技术(语义优化vs关键词)及算法透明度(封闭vs开放)。适用场景包括商业决策、行业权威建设及公共知识服务,帮助品牌在AI时代占据信息主导权。

解锁AI流量新红利!🚀 GEO优化(生成引擎优化)助您掌控AI搜索,让AI成为您的品牌最佳代言人! 1399

【即插即用模块】注意力篇 | TGRS 2025 | MFA聚特征+HPDown保细节+HFF融层级,三大模块各司其职,性能翻倍!

本文介绍了MTMLNet网络中的三大核心模块:MFA(多阶段特征聚合)、HPDown(混合池化下采样)和HFF(分层特征融合)。MFA通过双尺度深度卷积和注意力机制增强特征提取能力;HPDown结合平均池化和最大池化,有效保留下采样过程中的特征信息;HFF采用三注意力机制实现自适应特征融合。这三个模块协同工作,在红外小目标检测与分割任务中取得了SOTA效果。实验表明,各模块在特征提取、信息保留和融合方面均优于传统方法,可灵活应用于各类视觉任务中。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 285

Qt5的插件机制(6)--开发Qt插件时几个重要的宏

如何开发Qt插件,可以在Qt Assistant 中搜索"Qt Plugins"或"How to Create Qt Plugins",看看那篇manual中的介绍。 其中涉及到了几个宏 Q_DECLARE_INTERFACE( ClassName, Identifier) This macro associates the given Identifier (a string li

NewThinker_wei 的专栏 1万+

第10集:AIOps 平台架构设计!画出面试官最想看的系统全景图

本文介绍了如何将AIOps平台的六大功能模块整合为四层架构设计,并生成专业系统全景图。文章首先指出面试中架构设计能力的重要性,强调一张清晰的架构图能直观展现全局观。随后指导读者检查项目结构,准备绘图环境。核心部分详细拆解了四层架构:数据采集层(Prometheus、ELK等)、AI分析层(巡检、告警、预测等)、决策执行层(工作流引擎、自愈Agent)和展示交互层(API、控制台)。通过Python代码自动生成模块依赖关系图,并提供了面试讲解技巧。全文旨在帮助开发者在面试中系统性地展示项目架构设计能力。

qq_2937655951的博客 92

Qt5该插件机制(4)--QtMeta信息窗口小部件metaData

&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&a

weixin_34197488的博客 1301

C# 上位机高级功能实战:报警、历史回放与远程监控

本文介绍了工业上位机系统的高级功能实现,主要包括实时报警机制、历史数据回放和远程监控三部分。报警功能通过阈值检测实现异常提醒;历史回放利用数据库存储数据,通过定时器控制回放进度;远程监控提供TCP、WebSocket等多种数据传输方式。文章还给出了综合优化建议,如异步处理、报警去抖动等,最终形成一个包含数据采集、显示、存储、报表及高级功能的完整工业自动化闭环系统。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 750

用一张分析型 CDS Query 看清争议案件新增与结案节奏:C_OpenClosedDisputeCase 深度解读

应收账款争议管理中的关键CDS视图分析 摘要:C_OpenClosedDisputeCase是SAP系统中用于监控应收账款争议案件的重要CDS视图,提供三个时间窗口(当日、近5天、当月)的新增与结案数据。该视图通过"创建vs解决"的净变化指标,帮助财务团队实时掌握争议管理趋势,特别适用于多币种跨国企业的现金流管理。其核心价值在于将争议管理从被动"救火"转变为可量化运营,通过统一汇率换算和关键日期参数,为管理层提供标准化的运营仪表盘。视图采用特权访问模式,需通过上层应用

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 122

【Qt】插件机制详解:从原理到实战

本文详细解析Qt插件机制的核心原理和实现方法。Qt插件基于接口的动态加载技术,通过标准化接口(IPlugin)、插件元数据声明(Q_INTERFACES/Q_PLUGIN_METADATA)和QPluginLoader动态加载实现主程序与插件的解耦。文章以PluginPro主程序和PluginC插件为例,阐述了从接口定义、插件实现到动态加载的完整流程,并分析了Qt插件机制在松耦合、动态扩展、跨平台等方面的优势。该机制使系统功能可灵活扩展,显著提升可维护性。

weixin_47564581的博客 1340

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Qt插件学习笔记

本文介绍了Qt插件开发的核心流程和应用场景。首先阐述了插件机制的特点:插件依赖应用程序运行,但应用程序可独立运作,支持热插拔和动态更新。文章对比了插件与动态库的区别,指出插件通过接口编程实现松耦合,无需lib文件支持。详细讲解了Qt插件开发的四个关键步骤:定义通信接口、使用Q_DECLARE_INTERFACE宏声明接口、QPluginLoader加载插件以及接口测试方法。通过一个减法功能的示例,展示了主程序如何定义接口(DeclareInterface)并加载插件,以及插件项目如何实现接口(QTPlugi

菜一头包的博客 1199

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

qt插件元数据不包含一个有效的元数据_Qt5的插件机制(6)--开发Qt插件时几个重要的宏...

[插件代码接口类头文件 MyPluginInterface.h#ifndef INTERFACES_H#define INTERFACES_H#include #define QtPluginDemo_iid org.qt-project.Qt.PluginDemoclass MyPluginInt如何开发Qt插件,可以在Qt Assistant 中搜索"Qt Plugins"或"How to C...

weixin_39890102的博客 203

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Qt插件开发(1) - 开发实例

文章目录一、Qt插件机制1、简介2、Qt插件API3、插件调用4、创建插件二、实操1、创建工程2、插件子工程3、应用子工程三、定位插件(此段照搬《Qt高级——Qt插件开发》)四、参考 一、Qt插件机制 代码在Qt5.12.11和Qt6.1.1的linux版下测试ok。 1、简介 插件是一种遵循一定规范的应用程序接口编写出来的程序,定位于开发实现/扩展应用软件平台不具备的功能的程序。 具体的体现形式: linux: .so文件(动态库),.a文件(静态库) windows: *.dll文件(动态库), *.l

pk0127的博客 2134

Qt5 插件机制实现原理

Qt5 插件机制实现原理

lzqd1314的博客 449

Qt5的插件机制(3)--QLibraryPrivate类与QLibraryStore类

QLibraryPrivate 类的重要性 Qt中能加载库或插件的几个类:       QLibrary ,     QPluginLoader ,     QFactoryLoader ,     QStaticPlugin (暂时不研究这个)      QLibrary 和 QPluginLoader 依赖的'私有数据类'都是 QLibraryPrivate, 一个QL

NewThinker_wei 的专栏 6170

Qt Plugin插件开发

插件是一种遵循一定规范的应用程序接口编写出来的程序,定位于开发实现应用软件平台不具备的功能的程序。插件与宿主程序之间通过接口联系,就像硬件插卡一样,可以被随时删除,插入和修改,所以结构很灵活,容易修改,方便软件的升级和维护。Qt 提供了两种API用于创建插件:一种是高阶 API,用于扩展 Qt 本身的功能,如自定义数据库驱动,图像格式,文本编码,自定义样式等;一种是低阶 API,用于扩展 Qt 应用程序。本文主要是通过低阶 API 来创建 Qt 插件,并通过静态、动态两种方式来调用插件。

houxian1103的博客 2万+

Qt插件机制详解:QPluginLoader动态加载与模块化架构完整指南(Awesome_Qt_Learning)

**Awesome_Qt_Learning** 是一个面向 Qt 开发者的学习资源导航仓库,涵盖从基础知识到实战项目的学习资料、文献、书籍和示例。本文聚焦其中的进阶主题——**Qt插件机制**,带你理解 **QPluginLoader 动态加载**原理,掌握 **Qt 模块化架构**设计方法,帮助你在大型项目中实现功能的热插拔与扩展。 --- ## 一、为什么需要Qt插件机制?🔌 把插件想

gitblog_00949的博客 1219
上一篇: Qt5的插件机制(3)--QLibraryPrivate类与QLibraryStore类
下一篇: Qt5的插件机制(5)--QLibrary类与QPluginLoader类
NewThinker_wei
博客等级 码龄14年 521粉丝 51原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值