一、功能概述
1、概述
插件是遵循一定规范的应用程序接口编写出来的程序,独立于主程序并对主程序起辅助性质作用。使用插件的作用如下:
(1)将功能独立于主程序,保证主程序稳定的同时,方便功能的扩展。
(2)降低模块之间的依赖,便于并行开发。
(3)更新量小,当底层接口不变时,只需要更新以服务、插件形式存在的功能。
插件服务实现加载动态链接库的功能,并提供有动态增加、调用和删除服务或插件的方法。通过调用动态链接库中导出函数,获取插件和服务实例,并在多个服务或插件之间进行中介联系,能够相互访问而不直接发生联系,统一管理所有服务或插件的整个生命周期。
2、 整体设计思路
(1)单例模式
插件服务使用单例模式,在所有地方都共用一个插件服务实例。
(2)调用动态链接库
通过配置文件读取,获得所有要加载的动态链接库路径和服务或插件名。将动态链接库路径作为参数传递给LoadLib()函数进行动态链接库的加载。
(a)在window平台中,三个加载动态链接库的重要函数如下:
LoadLibrary():动态加载指定的动态链接库,将其映射到当前进程使用的地址空间。
GetProcAddress():检索指定的动态链接库中的输出库函数地址。
FreeLibrary():释放指定的动态链接库。对LoadLibrary的每一次调用都应该有一个对应的FreeLibrary调用。
(b)在linux平台下,相应的三个函数分别是:
dlopen():以指定模式加载指定的动态链接库。
dlsym():根据动态链接库操作句柄与符号,返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。
dlclose():关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
(3)调用服务或插件
在插件服务中提供GetService()和GetPlugin()进行服务和插件的调用,并使用m_servItems和m_pluginItems两个map型集合进行服务和插件的存储管理。当服务或插件已经存在时直接从这两个集合中获取服务或插件,当不存在时则调用服务或插件的动态链接库,使用动态链接库中CreateObject导出函数来创建对象,并进行服务或插件的存储。
二、功能设计
1、 设计原则
(1) 实现配置文件的读取。
借助tinyxml辅助类进行xml文件的读取,获得配置文件中需要加载的服务或插件名和相应动态链接库的路径。
(2) 实现动态链接库的加载
在linux环境中使用dlopen()、dlsym()和dlclose()函数进行动态链接库的加载、函数地址获取和动态链接库关闭的操作。
(3)实现服务和插件的管理
在插件服务中使用m_servItems和m_pluginItems两个map型集合进行服务和插件的存储管理。通过GetService()和GetPlugin()函数进行服务和插件的调用,使用Add()和Delete()函数增加和删除服务或插件。
2、 数据模型列表
序号 | 数据名称 | 类型 | 含义 |
1 | m_libHandle | void* | 动态链接库句柄 |
2 | m_libName | const char* | 动态链接库名称 |
3 | m_libItems | map | 服务或插件名和动态链接库实例 |
4 | m_serviceItems | map | 服务名和服务实例 |
5 | m_pluginItems | map | 插件名和插件实例 |
3、 功能列表如下:
序号 | 功能名称 | 相关函数 | 处理方式 |
1 | 调用动态链接库 | LoadLib() | 调用dlopen()函数加载动态链接库 |
2 | 获取服务或插件实例 | GetService() GetPlugin() | 调用dlsym()函数获取CreateObject导出函数地址,获取服务或插件实例 |
3 | 管理服务或插件实例 | AddService() DeleteService() AddPlugin() DeletePlugin() | 使用两个map类型的集合对服务、插件集合进行管理。根据服务名或插件名在集合中查找实例,当不存在时则加入到集合中,当存在时则在GetService()和GetPlugin()中返回该实例。 |
4 | 释放动态链接库 | FreeLib() | 调用dlclose()函数释放动态链接库 |
三、核心设计
1、 数据流程图
2、 类图
3、 时序图