Qt之插件

插件结构

QPluginLoader
+QObject* instance()
+QObjectList staticInstances()
+QVector staticPlugins()
QLibraryPrivate
+QAtomicPointer<std::remove_pointer>QtPluginInstanceFunction<::type> instanceFactory
+ QJsonObject metaData
+ QAtomicPointer<std::remove_pointer>Handle<::type> pHnd
QLibrary
QLibraryStore
- QMap<QString, QLibraryPrivate*> libraryMap

QPluginLoader:用于运行时加载插件

  • instance()方法获取插件的根组件,先使用load()加载库得到instanceFactory,然后调用该工厂方法创建实例
  • metaData方法获取插件的元数据,内部是QLibraryPrivate调用库的qt_plugin_query_metadata方法来获取
  • load()方法是从库获取方法qt_plugin_instance,并且存在instanceFactory变量中
  • unload()方法是卸载库,windows下是调用FreeLibrary,linux是调用dlclose,然后复位pHnd和instanceFactory
  • isLoaded()方法看是否加载完成,主要是看instanceFactory是否不为空
  • staticInstances()方法获取全局变量staticPluginList的实例副本
  • staticPlugins()获取全局变量staticPluginList

QLibrary:运行时加载动态库

  • resolve:解析得到函数指针
  • load:加载库
  • unload:卸载库
  • isLoaded:库是否加载完成

QLibraryStore:用于存储库名与QLibraryPrivate 映射关系

静态插件

注册

通过qRegisterStaticPluginFunction将静态插件添加到类型为StaticPluginList的全局变量中

typedef QVector<QStaticPlugin> StaticPluginList;
Q_GLOBAL_STATIC(StaticPluginList, staticPluginList)

void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin)
{
	staticPluginList()->append(plugin);
}

静态插件的创建是通过宏QT_MOC_EXPORT_PLUGIN

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#  define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
    static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \
    Q_PLUGIN_INSTANCE(PLUGINCLASS) \
    static QPluginMetaData qt_plugin_query_metadata_##PLUGINCLASSNAME() \
        { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \
    const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASSNAME() { \
        return { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \
    }
#else
#  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 reinterpret_cast<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; \
    }
#endif

宏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_IMPORT_PLUGIN

#define Q_IMPORT_PLUGIN(PLUGIN) \
        extern const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGIN(); \
        class Static##PLUGIN##PluginInstance{ \
        public: \
                Static##PLUGIN##PluginInstance() { \
                    qRegisterStaticPluginFunction(qt_static_plugin_##PLUGIN()); \
                } \
        }; \
       static Static##PLUGIN##PluginInstance static##PLUGIN##Instance;

QFactoryLoader结构

QFactoryLoader管理多个QLibraryPrivate

QFactoryLoaderPrivate
+QByteArray iid
+mutable QMutex mutex
+ QList<QLibraryPrivate*> libraryList
+ QMap<QString,QLibraryPrivate*> keyMap
+ QString suffix
+ Qt::CaseSensitivity cs
+ QStringList loadedPaths
QFactoryLoader
+void update()
+void refreshAll()
+QLibraryPrivate *library(const QString &key)
+QMultiMap~int, QString~ keyMap()
+int indexOf(const QString &needle)
+QList~QJsonObject~ metaData()
+QObject *instance(int index)

update:从应用的库目标集合中加载创建库,从库的元数据中获取IID,Keys,对应添加到QFactoryLoaderPrivate中的iid, loadedPaths, libraryList以及keyMap中
QFactoryLoader构造函数:会将自身添加到全局变量Q_GLOBAL_STATIC(QList<QFactoryLoader *>, qt_factory_loaders)
refreshAll:遍历全局变量qt_factory_loaders,调用update方法更新库信息
metaData:获取libraryList以及全局静态插件staticPlugins的元数据信息列表
instance:从libraryList和全局静态插件staticPlugins获取index位置 的插件实例,libraryList在前,静态插件staticPlugins在后
keyMap:先调用metaData得到所有插件的元数据,遍历获取所有的Keys字段的数据
indexOf:获取元数据列表中keys元素等于needle的元数据列表中的索引

模板函数

qLoadPlugin通过QFactoryLoader以及key来得到对应的工厂方法,然后调用create方法创建对应的QFactoryInterface

template <class PluginInterface, class FactoryInterface, typename ...Args>
PluginInterface *qLoadPlugin(const QFactoryLoader *loader, const QString &key, Args &&...args)
{
    const int index = loader->indexOf(key);
    if (index != -1) {
        QObject *factoryObject = loader->instance(index);
        if (FactoryInterface *factory = qobject_cast<FactoryInterface *>(factoryObject))
            if (PluginInterface *result = factory->create(key, std::forward<Args>(args)...))
                return result;
    }
    return nullptr;
}

相关推荐

  1. Qt

    2024-03-10 11:56:06       20 阅读
  2. Qt·Qt开发·导出类的步骤】

    2024-03-10 11:56:06       12 阅读
  3. Qt 框架

    2024-03-10 11:56:06       7 阅读
  4. 基于Qt扩展

    2024-03-10 11:56:06       18 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-10 11:56:06       14 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-10 11:56:06       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-10 11:56:06       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-10 11:56:06       18 阅读

热门阅读

  1. 从重庆——看未来数字化发展与趋势

    2024-03-10 11:56:06       21 阅读
  2. 设计模式 单例模式

    2024-03-10 11:56:06       17 阅读
  3. c++单例模式和call_once函数

    2024-03-10 11:56:06       18 阅读
  4. CSS教程(1)——CSS介绍

    2024-03-10 11:56:06       16 阅读
  5. 值传递和引用传递

    2024-03-10 11:56:06       17 阅读
  6. 利用SQL Server 进行报表统计的关键SQL语句与函数

    2024-03-10 11:56:06       19 阅读
  7. 【前端】尚硅谷Webpack教程笔记

    2024-03-10 11:56:06       21 阅读
  8. rabbitMQ

    rabbitMQ

    2024-03-10 11:56:06      17 阅读
  9. linux系统docker的使用命令

    2024-03-10 11:56:06       20 阅读
  10. el-table报错 error: [ElTable] prop row-key is required

    2024-03-10 11:56:06       19 阅读
  11. proteus8.9 示波器放大

    2024-03-10 11:56:06       18 阅读
  12. C++的萃取技术

    2024-03-10 11:56:06       16 阅读
  13. Vue实例声明详解

    2024-03-10 11:56:06       16 阅读
  14. 5.53 BCC工具之dbslower.py解读

    2024-03-10 11:56:06       19 阅读
  15. c++中利用指针或应用如何安全的获取数据

    2024-03-10 11:56:06       19 阅读