开源项目Hopsan代码梳理、流程分析
Hosan开源项目是液压、电力等行业的仿真开源软件,其由瑞典林平大学开发,可以仿真电力、液压等。更具体的了解,请参考:《Hopsan -- 液压、电力等行业的仿真开源软件》。Hosan开源项目编译参考:《Hopsan完全编译构建指南》、《Hopsan的源码编译》。代码梳理、流程分析如下:1。主流程启动如下(图有点小,请放大网页或下载图片到本地放大看):...
Hosan开源项目是液压、电力等行业的仿真开源软件,由瑞典林平大学开发,可以仿真电力、液压等。更具体的了解,请参考:《Hopsan -- 液压、电力等行业的仿真开源软件》。
Hosan开源项目编译参考:《Hopsan完全编译构建指南》、《Hopsan的源码编译》。
代码梳理、流程分析如下:
(1):HopsanEssentials的构造函数
在HopsanGUI/CoreAccess.cpp文件的顶部声明了一个hopsan::HopsanEssentials类型的全局变量gHopsanCore,本工程启动时,首先就会调用HopsanEssentials的构造函数,流程如下:
- 创建NodeFactory对象mpNodeFactory。
- 创建ComponentFactory对象mpComponentFactory。
- 如果是第一次调用构造函数,则创建QuantityRegister类对象mpQuantityRegister。在该类中,构造测试量和其单位的映射,如:速度为键,速度的单位m/s。
- 构造LoadExternal类对象mpExternalLoader,以便加载外部dll中包含的元件。
- 然后以步骤1创建的对象mpNodeFactory为参数,调用register_default_nodes函数,该函数返回后,mpNodeFactory就包含了系统所有默认的节点。
- 调用步骤2的mpComponentFactory对象中的registerCreatorFunction函数。注意:这个函数的第二个参数是一个函数指针,该函数指针是以类模板实现的,能支持任何返回值类型且无参数的任何函数。每个被创建的对象所在的类都有一个静态的Creator()函数,在其中创建该类的对象,如下:
- 做一些错误检测及清除错误状态的工作,如:看已经注册过的组件是否重复注册等。
(1.1)ClassFactory类
ClassFactory类是一个模板类,如下:
template <typename _Key, typename _Base, typename _Predicator = std::less<_Key> >
class ClassFactory
{
}
说明:
- _Base 是创出函数的返回值,即1节中6步骤中提到的registerCreatorFunction函数第2个参数表示的函数指针的返回值。
- Key是区分创建组件的关键字,本项目一般是字符串类型,如:“NodeSignal”字符串表示NodeSignal类的组件、DummyComponent表示DummyComponent类的组件等等。
- _Predicator是map的排序准则,默认是按第一个参数key小写排序。
NodeFactory、ComponentFactory都是ClassFactory模板类的实例,如下:
typedef ClassFactory<HString, Node> NodeFactory;
typedef ClassFactory<HString, Component> ComponentFactory;
(1.2)registerCreatorFunction
ClassFactory模板类的registerCreatorFunction功能如下:
- 将以key为键,创建组件的构造器也即函数指针为值的键值对, 插入名为mFactoryMap的map中,方便以后查找。
- 将key为键,创建组件的构造器也即函数指针为值构成的pair插入语 mRegStatusVector,以便在构造函数提示信息,参见1节中的步骤7。
(1.3)类的继承关系
(2)执行流程
(2.1)界面启动流程
- main函数被调用。
- 创建DesktopHandler对象,并调用该对象的setupPaths()函数安装一些目录。
- 创建Configuration对象,设置一些配置信息。
- 创建CopyStack对象。
- 创建GUIMessageHandler对象,用于处理应用程序的警告、错误、普通消息。
- 创建MainWindow对象,并调用其createContents函数创建各种面板、主界面等。
- 处理命令行参数。
- 闪屏提示。
- 调用MainWindow对象的initializeWorkspace函数,加载各种组件库等。
- 主程序、主界面启动。
流程如下:
(2.2) initializeWorkspace
流程如下:
- 以路径graphics/builtinCAF/hidden/builtin_hidden.xml为参数,InternalLib为第二个参数,Hidden为第三个参数调用LibraryHandler类的loadLibrary,即加载隐藏的内部组件。
- 调用LibraryHandler类的loadLibrary 函数加载
../componentLibraries/defaultLibrary/defaultComponentLibrary.xml配置文件中的组件。
3 调用LibraryHandler类的loadLibrary 函数加载如下目录下的组件:
../componentLibraries/autoLibs/
4 调用LibraryHandler类的loadLibrary 函数加载
graphics/builtinCAF/visible/builtin_visible.xml配置文件中的组件。
5 加载以前创建的外部库(在元件树)
6 创建plot widget对象gpPlotWidget,并隐藏。
7 创建FindWidget对象,并隐藏。
8 处理命令行中参数包含.hmf的参数,认为此参数就是模型文件,并加载该模型到视图。
9 调整元件树窗体部件、向闪屏界面发送加载组件完成信息。
(2.3)LibraryHandler类的loadLibrary函数(第1个参数是表示路径的字符串)
流程如下:
(2.4) LibraryHandler类的loadLibrary函数(第1个参数是SharedComponentLibraryPtrT类型)
- 读取第1参数即pLibrary的xml文件指向的信息,并绑定这些信息到pLibrary对象。
- 将pLibrary对象对象加入到类型为Qlist的mLoadedLibraries成员变量。
- 调用CoreLibraryAccess类的loadComponentLib函数加载pLibrary表示的库。
- 调用recompileLibrary函数编译该库。
- 再次调用CoreLibraryAccess类的loadComponentLib函数加载pLibrary表示的库。
- 如果pLibrary库的版本号小于0.3,则递归搜索pLibrary库目录下的xml文件且xml节点是hopsanobjectappearance的文件,并把该文件的绝对路径加入到pLibrary库的cafFiles
- 遍历pLibrary库的cafFiles,对每个遍历到的元素构建ModelObjectAppearance对象,也就是组件的外表对象,如:组件在树视图、设计视图上的名称、图标等。
- 如果步骤7)中的ModelObjectAppearance对象的typeName类型不是subsystem且不是ConditionalSubsystem,则去1.1节中的ClassFactory类中看这种类型是不是注册过,如果没注册或者其hmf文件不存在,则弹出加载这种类型的组件失败的错误。
- 构造ComponentLibraryEntry对象,并设置该对象的各种属性,并将该对象加入到mLibraryEntries,并告知闪屏界面,正在加载这个组件。
- 加载类型不为InternalLib的其它用户自定义的类型到配置文件。
- 发送contentsChanged信号,以便形成组件树视图。
(2.5)CoreLibraryAccess类的loadComponentLib
流程如下:
(2.6)组件注册文件的生成
子目录下的后缀名为.cci的文件内容如下:
pComponentFactory->registerCreatorFunction("SignalFirstOrderFilter",SignalFirstOrderFilter::Creator);
这些组件注册代码是由generateLibraryFiles.py通过python生成的
更多推荐
所有评论(0)