插件结构
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
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;
}