• Loren Blog

  • Menu

    插件生命周期

    为了编写 QtCreator 插件,你必须清楚在你启动或者关闭 QtCreator 的时候,插件管理器 所做的事情。 这一小节详细描述了这个过程以及插件将要经历的状态。

    在启动 QtCreator 时,通过设置环境变量 QT_LOGGING_RULES 的值为 qtc.extensionsystem*=true 开启插件相关的调试日志输出,你可以获得更多的信息。

    当你启动 QtCreator 时,插件管理器做了以下事情:

    1. 在它的搜索路径内查找所有的动态库,然后读取它们的元数据。 所有不包含元数据或者没有 org.qt-project.Qt.QtCreatorPlugin IID 的动态库将会被忽略。这是糟糕的原始数据可能会导致插件加载失败的第一点。

    2. 为某一个插件创建一个 ExtensionSystem::PluginSpec 的实例,该类是 插件规范中所有信息的容器,并且还追踪插件的状态。 你可以通过调用函数 plugins() 获取 ExtensionSystem::PluginSpec 的实例,或者在插件加载过后,通过插件的 pluginSpec 函数获得。

    3. 设置插件为 读取 状态。

    4. 验证每个插件的依赖是否存在并且兼容。想了解更多插件依赖的信息, 请参考 Plugin Specifications。

    5. 设置插件为 解决(Resolved)状态。

    6. 把排序好的插件放进一个列表中,我们叫它 load queue,插件的依赖 防止的插件的后面(但不是必须直接跟在插件的后面)。这能确保我们以适当的 顺序加载并初始化所有插件。

    7. 加载插件的动态库,然后以 load queue 中的顺序创建 IPlugin 的实例。 这时候,插件的构造函数将会被调用,被其他插件依赖的插件将会优先创建。

    8. 设置插件为 加载 状态。

    9. 以 load queue 中的顺序调用所有的插件的 initialize() 函数。在 initialize 函数中,插件必须保证所有导出的接口已设置,并且对于在其它插件中可用。 一个插件可以假定它所依赖的其他插件的导出接口已经被设置完成。 比如,Core 插件设置了 Core::ActionManager、https://doc-snapshots.qt.io/qtcreator-extending/core-editormanager.html[Core::EditorManager]以及 其他的可用的公共接口,则其他的插件都可以请求并使用它们。

      插件的 initialize() 函数适合

      • 向插件管理器对象池中注册对象(参考 The Plugin Manger, the Object Pool, and Registered Objects)

      • 加载设置

      • 增加新的菜单,以及向菜单中添加动作

      • 连接到其他插件的信号

    10. 设置插件为 初始化 的状态。

    11. 以 load queue 中的反向顺序调用所有插件的 extensionInitialized() 函数, 在调用 extensionInitialized 函数之后,插件应该完全初始化、设置并且运行。 一个插件可以假定它所依赖的其他插件都被设置完成,并且完成可以被其他插件扩展 部分的初始化。 比如,Core 插件将假定所有插件已经注册完它们的动作,并且完成动作管理器的初始化。

    12. 设置插件为运行状态。

    在启动的最后,插件 Core 的 Core::ICore 会发送两个信号。 在 QtCreator 的 UI 显示出来之前发送 coreAboutToOpen(), 之后发送 coreOpened()。

    在启动后,当 QtCreator 的事件循环运行时,插件管理器会以 load queue 的反向顺序调用 所有插件的 delayedInitialized() 函数。 这些调用会在主线程完成,但是会拆分出几毫秒的时间片来确保 QtCreator 的响应。 在 deployedInitialized 函数内,插件可以执行非关键的初始化,如果在启动阶段完成, 可能会不必要的延迟 QtCreator 的显示。

    在所有延迟初始化完成后,https://doc-snapshots.qt.io/qtcreator-extending/extensionsystem-pluginmanager.html[插件管理器] 会发送信号 initializedDone()。

    在关闭之前,插件 Core 的 Core::ICore 会发送信号 coreAboutToClose()。 之后,插件管理器会启动它的关闭程序:

    1. 以 load queue 中的顺序调用每个插件的 aboutToShutdown() 函数,插件需要执行 加速实际关闭的措施,比如断开可能会调用的信号链接。如果一个插件需要延迟真正的关闭一会, 比如为了完整的退出,需要等待额外的进程结束,插件可以通过函数 Extension::IPlugin::AsynchronousShutdown 返回。这将会使插件管理器在下一步等待,并保持主事件循环的运行,直到所插件发送 asynchronousShutdownFinished() 信号请求 AsynchronousShutdown。

    2. 以 load queue 中的反向顺序删除 ExtensionSystem::IPlugin 实例销毁所有的插件。 在这时候插件的析构函数被调用,插件应该通过释放内存或者其他资源自己清理。

    原文地址

Posts

  • Perl6的符号表
  • Perl6调用C接口
  • 插件生命周期(QtCreator文档翻译)
  • 1的补码与2的补码
  • 归纳操作符(reduce operator)
  • emacs config
  • c++模板的技巧示例
  • 简单括号匹配
  • IA-32算术移位与逻辑移位
Loren Blog

将会写一些关于C/C++/Perl6 的小文章,记录一些知识点。


© 2017 araraloren | araraloren@github.com