CAX软件插件化设计实现牛刀小试
为什么要插件化?
定义插件接口:契约先行
OcadIMenuPlugin.h):
initialize:插件加载时调用,传入主窗口指针,插件可以自由地向OcadRibbon界面添加菜单、工具栏等UI元素。
shutdown:插件卸载时清理资源、移除UI,保证热插拔干净利落。
Q_DECLARE_INTERFACE宏配合固定IID,是Qt插件系统的“身份证”,确保运行时类型安全。
主框架只依赖这个抽象接口,而不依赖任何具体插件,真正实现了“面向接口编程”。
插件管理器:动态加载的容器
接下来实现插件管理器(OcadPluginsManger.h),负责插件的加载、卸载和生命周期管理:

PluginRecord记录每个插件的文件路径、加载器指针和插件对象指针,用std::vector<std::unique_ptr>>管理,自动释放资源。
loadPlugin内部使用QPluginLoader加载动态库,通过qobject_cast<OcadIMenuPlugin*>转换为接口指针,然后调用initialize(m_mainWindow),让插件注册自己的功能。
unloadPlugin先调用插件的shutdown(),再删除QPluginLoader,实现动态卸载。
loadConfig支持通过配置文件指定要加载的插件列表,甚至可以通过传入的pluginsMenu菜单动态生成启用/禁用选项,比简单扫描目录更灵活。
具体插件实现:可插拔的功能块

多重继承QObject和自定义接口,获得Qt元对象能力(信号槽、动态类型)。
Q_PLUGIN_METADATA声明插件元数据(版本、作者等),Qt可通过loader->metaData()读取,实现按需加载或版本校验。
Q_INTERFACES告诉Qt这个类实现了OcadIMenuPlugin,使qobject_cast能正确工作。
成员变量保存主窗口指针,shutdown时可以准确移除自己添加的内容,避免残留。
整体架构亮点与后续展望
接口与实现严格分离:公共接口定义在独立模块中,主框架和具体插件都依赖它,形成稳定的中间层。
动态加载与卸载:利用QPluginLoader实现运行时的功能增减,无需重启软件。
与UI框架深度集成:插件可自由扩展OcadRibbon界面,主框架无需预知任何菜单项,扩展性极强。
配置化加载:支持通过配置文件管理插件清单,为产品的模块化交付和个性化定制打下基础。
后续可以进一步优化:增加插件依赖管理、建立插件间通信机制(如服务总线)、完善热插拔时的UI清理等
效果展示:
编译一个完整的插件和设置配置文件后:

主程序启动效果:


主程序大小仅87KB
夜雨聆风