本文归属于 Qt实验室-CSDN博客 系列文章
这里以Qt Creator 4.15.2版本的源码为示例进行分析
源码结构如下,为了追溯其插件加载过程,从main.cpp入手
Qt Creator的插件目录,生成的插件,好几十个呢
int main(int argc, char **argv)中以下代码创建插件的管理
- PluginManager pluginManager;
- PluginManager::setPluginIID(QLatin1String("org.qt-project.Qt.QtCreatorPlugin"));
- PluginManager::setGlobalSettings(globalSettings);
- PluginManager::setSettings(settings);
int main(int argc, char **argv)中以下设置插件的读取目录,读取所有插件信息
- const QStringList pluginPaths = getPluginPaths() + options.customPluginPaths;
- PluginManager::setPluginPaths(pluginPaths);//读取插件目录下的插件
从 PluginManager::setPluginPaths(pluginPaths)调用追溯到如下
- void PluginManagerPrivate::setPluginPaths(const QStringList &paths)
- {
- qCDebug(pluginLog) << "Plugin search paths:" << paths;
- qCDebug(pluginLog) << "Required IID:" << pluginIID;
- pluginPaths = paths;
- readSettings();
- readPluginPaths();
- }
继续追溯void PluginManagerPrivate::readPluginPaths()
- for (const QString &pluginFile : pluginFiles(pluginPaths)) {
- PluginSpec *spec = PluginSpec::read(pluginFile);
- PluginSpec *PluginSpec::read(const QString &filePath)
- {
- auto spec = new PluginSpec;
- if (!spec->d->read(filePath)) { // not a Qt Creator plugin
- delete spec;
- return nullptr;
- }
- return spec;
- }
其中bool PluginSpecPrivate::read(const QString &fileName)方法读取了插件的基本信息
从main函数中的 PluginManager::loadPlugins();开始追溯插件的加载
- void PluginManagerPrivate::loadPlugins()
- {
- //所有插件都会从loaded-->initialized-->running
- const QVector<PluginSpec *> queue = loadQueue();
- Utils::setMimeStartupPhase(MimeStartupPhase::PluginsLoading);
- for (PluginSpec *spec : queue)
- loadPlugin(spec, PluginSpec::Loaded);
- Utils::setMimeStartupPhase(MimeStartupPhase::PluginsInitializing);
- for (PluginSpec *spec : queue)
- loadPlugin(spec, PluginSpec::Initialized);
- Utils::setMimeStartupPhase(MimeStartupPhase::PluginsDelayedInitializing);
- Utils::reverseForeach(queue, [this](PluginSpec *spec) {
- loadPlugin(spec, PluginSpec::Running);//从这里开始加载插件...step2
- if (spec->state() == PluginSpec::Running) {
- delayedInitializeQueue.push(spec);
- } else {
- // Plugin initialization failed, so cleanup after it
- spec->d->kill();
- }
- });
-
- ...
- }
插件加载的几个主要步骤,load, initialize, run
在 void PluginManagerPrivate::loadPlugin(PluginSpec *spec, PluginSpec::State destState)中
- switch (destState) {
- case PluginSpec::Loaded:
- profilingReport(">loadLibrary", spec);
- spec->d->loadLibrary();
- profilingReport("
, spec); - break;
- case PluginSpec::Initialized:
- profilingReport(">initializePlugin", spec);
- spec->d->initializePlugin();
- profilingReport("
, spec); - break;
- case PluginSpec::Stopped:
- profilingReport(">stop", spec);
- if (spec->d->stop() == IPlugin::AsynchronousShutdown) {
- asynchronousPlugins << spec;
- connect(spec->plugin(), &IPlugin::asynchronousShutdownFinished,
- this, &PluginManagerPrivate::asyncShutdownFinished);
- }
- profilingReport("
, spec); - break;
- default:
- break;
- }
继续追溯bool PluginSpecPrivate::loadLibrary()
- if (!loader.load()) {//这里是加载插件
- hasError = true;
- errorString = QDir::toNativeSeparators(filePath)
- + QString::fromLatin1(": ") + loader.errorString();
- return false;
- }
合格的插件需要继承自IPlugin抽象类
以CppEditorPlugin为例
class CppEditorPlugin : public ExtensionSystem::IPlugin
看一下IPlugin类
-
- #pragma once
-
- #include "extensionsystem_global.h"
-
- #include
-
- namespace ExtensionSystem {
-
- namespace Internal {
- class IPluginPrivate;
- class PluginSpecPrivate;
- }
-
- class PluginManager;
- class PluginSpec;
-
- class EXTENSIONSYSTEM_EXPORT IPlugin : public QObject
- {
- Q_OBJECT
-
- public:
- enum ShutdownFlag {
- SynchronousShutdown,
- AsynchronousShutdown
- };
-
- IPlugin();
- ~IPlugin() override;
-
- virtual bool initialize(const QStringList &arguments, QString *errorString) = 0;
- virtual void extensionsInitialized() {}
- virtual bool delayedInitialize() { return false; }
- virtual ShutdownFlag aboutToShutdown() { return SynchronousShutdown; }
- virtual QObject *remoteCommand(const QStringList & /* options */,
- const QString & /* workingDirectory */,
- const QStringList & /* arguments */) { return nullptr; }
- virtual QVector
createTestObjects() const ; -
- PluginSpec *pluginSpec() const;
-
- signals:
- void asynchronousShutdownFinished();
-
- private:
- Internal::IPluginPrivate *d;
-
- friend class Internal::PluginSpecPrivate;
- };
-
- } // namespace ExtensionSystem
实现具体的插件类时,以下方法是必须重写的
virtual bool initialize(const QStringList &arguments, QString *errorString) = 0;