[软件架构]进程内插件系统的架构设计
为了保证软件的可持续集成能力,为了使软件在编写过程中灵活方便,自然地会想到把软件做成一个插件系统。但是怎么做呢?想了一阵子,算是有个头绪,下面讲出来,希望大家提提意见。
目标
只是实现进程内的插件系统,也就是说所有插件和主框架在一个地址空间内运行,这样可以共享内存。
技术方案
实现方法是使用DLL文件。主框架将插件的DLL加载到自己的进程空间内,这样可以容易的设置回调函数(等等)。插件必须提供预先定义的几个接口供主框架识别插件版本、类型、功能(等等)。
接口定义
主框架:提供一个IFrameWork接口,主要是向插件暴露内部接口,包括插件从主框架获取参数,包括插件向主框架返回数据等等。
子插件:提供Init(插件初始化)、Uninit(插件注销)、QueryFrameWork(请求主框架接口)、Invoke(执行子插件功能)等函数。
工作流程
1. 主框架在程序中设定子插件的搜寻路径(所有插件应该集中放在一个目录下),并在该路径下开始搜寻插件文件。
2. 找到一个插件文件—LL文件)后,使用LoadLibrary函数将该插件加载到进程内。
3. 检查插件的接口(导出函数),即通过GetProcAddress函数获取插件暴露的接口地址。这里需要注意的一点是导出的函数需要使用cstdcall方式,这样导出符号不会被修饰。或者使用DEF文件导出。另外预先定义的插件必须暴露的所有接口都必须正确实现和暴露,否则认为该插件损坏。
4. 确定插件完整性后,即调用Init接口对插件内部进行初始化。当然也有可能插件内部根本不需要额外的初始化动作。
5. 将主框架内实现的IFrameWork接口设置(类似回调的方式)给插件。
6. 主框架在插件被需要的时候调用插件的Invoke函数执行插件功能。
7. 在插件从主框架卸载之前,调用Uninit函数进行反初始化动作,以确保插件内资源被释放。
8. 主框架调用FreeLibrary函数将插件从进程空间内卸载。