StateWizard VC++ 插件和带源代码的引擎
一个跨平台的面向状态的应用框架,以及一个类似于 ClassWizard 的、支持双向 UML 动态建模/开发工具,可在常用 IDE 中运行。旨在为 Win32/Linux 提供并发、分布式和实时应用开发工具。
- 下载状态机引擎源代码 - 141.13 KB
- 下载 StateWizard Standard VS2003 插件源代码 - 318.92 KB
- 下载 StateWizard Standard VS2005 插件源代码 - 325.61 KB
- StateWizard Standard 安装
- 在主页快速下载最新版本
引言
在软件系统日益复杂、并发和实时化日益增强的环境中,建模语言和工具的选择成为许多项目成功的关键。
本文介绍了一个跨平台的面向状态的应用框架,使用标准的 C++/C 为 Win32/Linux 编写,以及一个类似于 ClassWizard 的双向 UML 动态建模/开发工具:StateWizard。
关注点
下表列出了为本项目编写的广泛技术
- 使用 DTE 为 VS2003 或 VS2005 进行 Visual Studio 插件开发
- COM 开发
- 异步函数调用
- 跨平台操作系统相关库
- 高质量状态机引擎
- Win32 映射文件分析
有什么新鲜事?
UML:标准
统一建模语言TM - UML - 是 OMG 最常用的规范,也是世界各地用于建模应用程序结构、行为和架构,以及业务流程和数据结构的方式。[1]
UML 动态视图用于表达和建模系统随时间推移的行为,通过状态机、顺序图和活动图呈现。
状态机图捕捉软件系统的行为。状态机可用于建模类、子系统或整个应用程序的行为。它们还通过协议或事件驱动的系统,提供了与外部实体进行通信的绝佳方式。
顺序图用于显示用户、屏幕、对象和系统内实体之间的交互。它们提供了对象之间随时间传递消息的顺序图。
为什么选择 UML StateWizard?
你可能会问,为什么是 UML StateWizard,而市面上已经有许多优秀的 UML 工具,如 Rational Rose、VisualState 等。我们的答案是:
- StateWizard 是一个类 ClassWizard、简单高效的 IDE 集成工具
- StateWizard 是一个功能齐全的 UML 工具 [2]
- StateWizard 基于扎实优化的概念、实现选择和数据结构
- StateWizard 具有许多有用的“杂项”功能
1. 类 ClassWizard 式的、简单高效的 IDE 集成工具
在开发 StateWizard 时,我们始终牢记提供一个直观易用的解决方案。
- 就像 Microsoft Visual C++ ClassWizard 一样,StateWizard 在集成开发环境内运行。无需在工具之间切换进行设计/开发,而许多 UML 建模工具则作为独立应用程序运行。
- 无中间建模文件,直接根据源代码中的一组特定宏和标志构建 UML 图。
- StateWizard 可快速构建基于状态机的框架应用程序。它高效地将状态图直接编码为平台无关的标准 C/C++。
- StateWizard 为嵌入式系统开发提供状态跟踪、模拟和调试功能。
UML StateWizard 支持以下 IDE:
- Visual C++ 6.0
- eMbedded Visual C++ 4.0
- Visual Studio 2003
- Visual Studio 2005
2. 功能齐全的 UML 工具
一些 CASE 工具允许用户从一组规范生成代码。然而,有时生成的代码可能并不太有用,因为它可能冗长且难以理解。StateWizard 提供了以下解决方案:
- UML 图支持:StateWizard 支持构成 UML 状态机的九种图。它支持状态树和状态图绘制。
- 正向工程:StateWizard UML 工具的应用不止于对图进行图形化描述。由于图中定义的系统结构被开发人员翻译成实际源代码,StateWizard 通过生成带有方法存根的状态机框架源代码来弥合这一步骤。开发人员可以拿走这些存根代码并填充实际代码。这种自动化生成源代码的特性称为正向工程。
- 逆向工程:逆向工程与正向工程完全相反。在逆向工程中,StateWizard 加载应用程序/系统的所有文件,识别应用程序之间的状态关系,并基本上重建整个状态机结构及其所有关系。
- 双向工程:除了正向工程和逆向工程之外,另一个有用的功能是双向工程。正向工程和逆向工程本质上是一次性活动,它们接受输入并生成所需的输出。双向工程扩展了这些功能。软件设计的一个重要规则是,没有设计是永恒不变的。这对于小型系统和大型系统都同样适用。在开发过程中,UML 模型中定义的设计结构会发生变化,以适应设计中未预料到的物理实现差异。将系统设计与源代码中的更改保持同步变得非常困难。双向工程功能使用户能够让 UML 工具将模型与应用程序代码中的更改同步。StateWizard 倾向于强制 UML 工具能够根据代码部分的修改实时同步其模型。例如,开发人员可以对状态图进行拖放操作,之后源代码也会随之更改;反之,开发人员可以直接修改代码部分,修改将自动显示在状态图上。这使得 StateWizard 能够充当状态图和源代码之间的桥梁。
- 文档:StateWizard 为设计人员提供了一种在图表中记录设计决策的方法。设计人员可以保存状态图为 BMP 文件,并将状态树保存为文本文件。
3. StateWizard 基于扎实优化的概念和实现选择
除了应用程序和端口等创新的概念外,StateWizard 还通过优化的数据结构和实现选择进行设计,保证了高效的应用代码生成和双向工程。在其功能中,我们可以指出:
状态图
状态图在没有沉重、昂贵的 CASE 工具的情况下对嵌入式系统进行建模。状态图为您提供了应用程序逻辑结构和流程的“鸟瞰图”。它以图形方式构建状态层次结构,将子状态嵌套在其父模式中。状态图相对于状态树的另一个主要优势是,它以从一个状态到另一个状态的箭头形式显示每个状态的转换。如果开发人员选择了一个状态或转换,然后右键单击鼠标,StateWizard 将根据所选状态或转换通过菜单提供一个操作列表。
状态树
状态树是状态机程序员的助手,位于 VC 工作区选项卡窗口中。在编码时,它将提供一个状态机框架。它使开发人员能够轻松执行某些路由任务,例如创建状态机应用程序、创建状态层次结构、为状态定义入口函数和退出函数,以及定义事件处理程序。运行时,它是所有活动应用程序的状态跟踪器。如果开发人员选择了一个状态树项,然后右键单击鼠标,StateWizard 将根据所选项目、应用程序或状态通过菜单提供一个操作列表。
StateTree 和 StateChart 如何支持逆向工程
除了 C/C++ 源代码之外,没有额外的状态机信息。StateTree 和 StateChart 如何支持逆向工程?就像 Visual C++ ClassWizard 一样,StateWizard 定义了一组宏来构建状态机、定义状态、子状态、声明事件处理程序和状态转换。
例如,以下 C++ 宏定义了一个名为 Player 的状态机,具有以下状态:
Player
(PowerDown
,PowerUp
(Playing
,Pause
))
以及状态转换
- (
EXT_EVENT_ID_POWER, PowerDown
->PowerUp, OnPowerDownEXT_EVENT_ID_POWER
) - (
EXT_EVENT_ID_POWER, PowerUp
->PowerDown, OnPowerUpEXT_EVENT_ID_POWER
) - (
EXT_EVENT_ID_PAUSE_RESUME, Playing
->Pause, OnPlayingEXT_EVENT_ID_PAUSE_RESUME
) - (
EXT_EVENT_ID_PAUSE_RESUME, Pause
->Playing, OnPauseEXT_EVENT_ID_PAUSE_RESUME
)
SME_HANDLER_CLASS_DEF(Player)
SME_BEGIN_STATE_DEF(Player,Player)
/*{{SME_STATE_DEF(Player,Player)*/
SME_STATE_ENTRY_FUNC(PlayerEntry)
SME_STATE_EXIT_FUNC(PlayerExit)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(Player,PowerDown)
/*{{SME_STATE_DEF(Player,PowerDown)*/
SME_STATE_ENTRY_FUNC(PowerDownEntry)
SME_STATE_EXIT_FUNC(PowerDownExit)
SME_ON_EVENT(EXT_EVENT_ID_POWER,OnPowerDownEXT_EVENT_ID_POWER,PowerUp)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(Player,PowerUp)
/*{{SME_STATE_DEF(Player,PowerUp)*/
SME_STATE_ENTRY_FUNC(PowerUpEntry)
SME_STATE_EXIT_FUNC(PowerUpExit)
SME_ON_EVENT(EXT_EVENT_ID_POWER,OnPowerUpEXT_EVENT_ID_POWER,PowerDown)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(Player,Playing)
/*{{SME_STATE_DEF(Player,Playing)*/
SME_STATE_ENTRY_FUNC(PlayingEntry)
SME_STATE_EXIT_FUNC(PlayingExit)
SME_ON_EVENT(EXT_EVENT_ID_PAUSE_RESUME,OnPlayingEXT_EVENT_ID_PAUSE_RESUME,Pause)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(Player,Pause)
/*{{SME_STATE_DEF(Player,Pause)*/
SME_STATE_ENTRY_FUNC(PauseEntry)
SME_STATE_EXIT_FUNC(PauseExit)
SME_ON_EVENT(EXT_EVENT_ID_PAUSE_RESUME,OnPauseEXT_EVENT_ID_PAUSE_RESUME,Playing)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
/*{{SME_STATE_STATETREE_SEPARATOR}}*/
SME_BEGIN_STATE_TREE_DEF(Player)
/*{{SME_STATE_TREE_DEF(Player)*/
SME_STATE(Player,Player,SME_INVALID_STATE,PowerDown)
SME_STATE(Player,PowerDown,0,-1)
SME_STATE(Player,PowerUp,0,Playing)
SME_STATE(Player,Playing,PowerUp,-1)
SME_STATE(Player,Pause,PowerUp,-1)
/*}}SME_STATE_TREE_DEF*/
SME_END_STATE_TREE_DEF
/*{{SME_DEC_IMP_SEPARATOR}}*/
SME_APPLICATION_DEF(Player, "Player")
状态机运行环境
实时或嵌入式应用程序的设计通常涉及将应用程序软件分解为对象,其中一些对象可能实现有限状态机来控制进程或系统。这些控制对象的示例可能是电话交换系统中的呼叫控制类,或医疗器械中的治疗控制类。有限状态机是响应式、事件驱动的控制结构,其行为由接收到的事件及其之前的事件历史决定。其他非响应式类提供计算或数据检索服务,不需要维护机器状态或刺激历史来完成其功能。
在 StateWizard 环境中,这些活动类实现状态机并可以处理输入事件。StateWizard 状态机引擎管理这些类并充当事件调度程序。
状态机对象可以处于活动状态或非活动状态。状态机引擎仅将事件分派给活动状态机对象。非活动状态机对象不处理事件。
StateWizard 运行时环境的架构如下所示,显示了运行在状态机引擎之上的应用程序对象和线程。RTOS 虚拟层提供了一个通用的接口,用于常见的 RTOS 服务,如信号量、互斥锁和线程控制。服务提供商层是与低级模块和硬件接口的接口层。模拟或目标环境层提供与目标环境或目标环境模拟的接口。软件开发过程中经常使用模拟,当真实的硬件尚未可用时,或者当需要广泛的调试功能但目标上不可用时。
状态机线程
多个活动状态机对象可以在单个线程上下文中运行。线程上下文标识一个独立的执行线程,并包含线程标识符、一组对象、内部事件池和几个事件挂钩函数。
状态机应用程序框架
StateWizard 为状态机对象提供两个应用程序框架:
- 标准嵌入式 C
- 标准 C++
对于标准 C++ 应用程序框架,状态机对象由 C++ 类构造。
状态机对象激活
要激活,状态机对象通过调用 SmeActivateObj()
函数向状态机引擎标识自身。以下示例创建了一个名为 Player1
的 Player
状态机对象。Player1
在一个名为 AppThreadProc
的单独线程下运行。线程上下文是 g_AppThreadContext
。
void* AppThreadProc(void *Param)
{
// The second parameter (NULL) is the state machine Player1's parent.
SmeActivateObj(&Player1,NULL);
SmeRun();
}
SME_OBJ_DEF(Player1,Player)
SME_THREAD_CONTEXT_T g_AppThreadContext;
XTHREADHANDLE ThreadHandle = 0;
// Install thread local storage data functions.
XTlsAlloc();
SmeSetTlsProc(XSetThreadContext, XGetThreadContext);
// Initialize the engine
SmeInitEngine(&g_AppThreadContext);
// Install external event handler functions.
// They act as a plug-in of the state machine engine.
SmeSetExtEventOprProc(XGetExtEvent, XDelExtEvent, XPostThreadExtIntEvent,
XPostThreadExtPtrEvent, XInitMsgBuf, XFreeMsgBuf);
int ret = XCreateThread(AppThreadProc, NULL, &AppThreadHandle);
// The second parameter is the parameter for the thread entry function.
播放器控制面板可以将外部事件发布到运行线程的事件队列中。引擎会将它们分派给活动的应用程序 Player1
。
XPostThreadExtIntEvent(&g_AppThreadContext, EXT_EVENT_ID_POWER, 0, 0,
NULL,0,SME_EVENT_CAT_OTHER);
状态机对象去激活
通过调用 SmeDeactivateObj()
函数来去激活状态机对象。以下语句去激活 Player1
状态机对象。
SmeDeactivateObj(&Player1);
服务提供商
状态机应用程序可能与低层(其他模块)或硬件(称为服务提供商)紧密协作。服务通过一组可供服务用户(应用程序)使用的原语(操作)来正式定义。这些原语告诉服务执行某个操作,或报告对对等组件/实体所采取的操作。服务原语分为四类:
- 请求
- 指示
- 响应
- Confirm
[计算机网络,Andrew S.Tanenbaum]。请求和确认原语可以实现为服务调用的形式。指示和响应原语可以实现为外部事件发布的形式。
活动状态机对象可以使用以下机制之一与服务提供商通信,以交换信息:
- 同步服务调用。这些同步服务调用可能会阻塞,在操作完成后将控制权返回给应用程序。由于大多数实时系统必须在预定的时间内响应外部事件,因此不同步服务调用。
- 异步服务调用。异步函数不阻塞,继续执行并在操作完成之前返回。
- 主动事件指示。这些事件从服务组件发布到客户端组件,无需任何请求。例如,可能是由硬件中断服务例程发布的事件。
平台无关的嵌入式系统开发
嵌入式系统市场上有许多不同的实时操作系统(RTOS)。每个不同的 RTOS 都提供不同的 API 来访问一组通用的系统服务。StateWizard RTOS 虚拟层提供了一个平台独立的适配层,允许状态机在不同的操作系统之间移植。我们可以将应用程序从一个 RTOS 迁移到另一个 RTOS,而无需更改应用程序代码。RTOS 虚拟层中的外部事件接收器充当状态机引擎的插件。
模拟器
应考虑模拟器的情况:
- 硬件不可用或成本高昂
- 需要广泛的调试功能
模拟器是测试工具的几个重要类别之一。它们模拟软件最终将运行的环境,并通常包含有用的调试功能。它们还使测试人员能够更有效地控制测试环境,并且当稀缺的目标硬件必须在工程师之间共享时,可以节省关键的开发资源。
模拟允许在硬件原型可用之前开始软件测试。它还随着系统的大小和复杂性进行扩展,有助于在开发周期早期识别和解决问题,此时修复成本仍然较低。
在模拟环境中,开发人员可以在桌面平台(例如 Windows 或 Linux)上模拟服务提供商。这些模拟服务具有与目标服务提供商接口相同的接口。迁移到目标环境时,在模拟环境中测试过状态机应用程序后,应只需少量工作即可将其集成到实际环境中。活动应用程序可以调用服务提供商提供的服务,并通过 RTOS 函数接收由服务提供商触发的外部事件。
您可以将 StateWizard 应用于:
- 通过窗口消息钩子技术进行基于状态机的 Win32/WinCE 程序开发
- 跨平台嵌入式系统建模和模拟
具有产品质量的 StateWizard Pro 引擎
- 分层状态机
- 通过将状态树定义分离到多个 C/C++ 文件中,支持具有数百个状态的大型状态机
- 状态历史信息和历史转换
- 事件处理时的守护转换
- 条件伪状态
- 连接伪状态
- 多线程正交状态
- 内置状态计时器;进入状态时自动启动内置计时器,退出状态时停止计时器
- Linux/Win32 的跨平台事件循环和操作系统相关 API 库
在此处 下载 StateWizard Pro。
许可
您可以从这里 下载更多信息,这是 UML StateWizard 开源项目的官方网站,采用 LGPL 许可证。