每一个大型的系统都有自己定义良好的系统架构。很好地理解这些架构,能够很大的提高我们自己的设计水平。Qt Creator 同样也不例外。本章我们将学习 Qt Creator 的基本架构,进而更好地理解如何编写 Qt Creator 的插件。
Qt Creator 概览
Qt Creator 的核心就是一个插件加载器,其所有功能都是通过插件实现的。
Qt Creator 最主要的功能是在名为 Core 的插件中实现的(Core::ICore
)。我们已经在前面的章节中见到过这个插件。在后面的内容中,我们将把 “core plugin” 简称为 Core。
插件管理器(ExtensionSystem::PluginManager
)提供插件合作机制,这样就能让插件相互依赖,共同工作。
到底什么是“插件”?
从最底层看,插件可以看成一个动态链接库(Windows 上的 DLL 文件,Linux 上的 SO 文件,Mac 上的 DYLIB 文件)。从开发者的角度来说,插件是一个模块,这个模块应该:
- 在一个类中实现
ExtensionSystem::IPlugin
接口。下文中,我们将把这个类称为“插件类”。 - 使用
Q_EXPORT_PLUGIN
宏导出插件类。 - 为这个插件提供一个 pluginspec 文件,用于描述插件的元信息。
- 向其它插件暴露一个或多个对象。
- 搜寻其它插件暴露出来的可用的一个或多个对象。
我们在前面的章节中已经或多或少接触到上面所说的前三点,但是还没有接触到后两点。
什么是暴露出的对象?
暴露出的对象会加入到PluginManager
的对象池。PluginManager
的allObjects()
函数用于获得这个对象池中所有QObject
对象的指针列表。下面的代码演示了如何将这个对象列表导出到QListWidget
组件:
#include <extensionsystem/pluginmanager.h> ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); QList<QObject*> objects = pm->allObjects(); QListWidget* listWidget = new QListWidget; Q_FOREACH(QObject* obj, objects) { QString objInfo = QString("%1 (%2)") .arg(obj->objectName()) .arg(obj->metaObject()->className()); listWidget->addItem(objInfo); }
如果我们使用上面的代码,将所有对象在一个QListWidget
中显示出来时,我们会得到如下效果(大家可以尝试修改上一章中我们编写的 DoNothing 插件。具体方案是使用上面代码替换about()
函数的代码):
从上图中显示的类名可以看出,这些对象来自不同的插件。现在,我们可以更好地定义所谓的“暴露出的对象”了:
一个对外暴露的对象是由一个插件暴露的
QObject
(或其子类)的实例,这个对象存在于对象池中,并且可供其它插件使用。
如何让插件“暴露”对象?
我们有三种方法可以让插件暴露其对象:
- IPlugin::addAutoReleasedObject(QObject*)
- IPlugin::addObject(QObject*)
- PluginManager::addObject(QObject*)
IPlugin::addObject()
和IPlugin::addAutoReleasedObject()
其实都是调用的PluginManager::addObject()
函数。所以,这些IPlugin
的函数仅仅为了使用方便。我们的建议是,使用IPlugin
的函数添加对象。addAutoReleasedObject()
和addObject()
的唯一区别是,前者添加的对象会在插件销毁的时候自动按照注册顺序从对象池中移除并 delete。
在任意时刻,我们都可以使用IPlugin::removeObject(QObject*)
函数将对象从对象池中移除。