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;
}
  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值