第7回:关于计算机模拟状态机在工程实践编程中的实际应用(2)

上一篇文章介绍了作者开发应用程序用到的编译器,编辑器和调试器,本篇文章用于介绍作者通常使用的工程目录和工程文件(对于Qt来说,是后缀名为.pro的文件),以及工程文件内容编写。

以当前应用为例,作者会在计算机操作系统任一文件夹下建立如下文件夹与工程文件,作为源文件保存位置(在windows命令窗口使用tree命令):

F:\SMFRAME-WORK-MASTER
├─bin
├─config
├─data
├─file
├─includes
├─lib
├─setup
└─src
    ├─base
    ├─gui
    └─Logic

其中:

  • bin:保存生成的可执行文件,以及额外的动态链接库
  • config:保存程序配置文件,针对程序或者设备本身的元信息。
  • data:保存参数文件,程序的输入输出文件。
  • file:保存参考资料文件。
  • includes:保存动态链接库对应的lib文件和程序生成的静态链接文件。
  • setup:保存安装脚本和打包安装程序时需要额外包含的模块。
  • src:保存源文件,作者一般使用三个源文件夹保存项目的不同抽象层次,其中:
    • base:保存通用的底层抽象定义的源文件,例如通用的状态、变量和状态机定义,并编译成静态链接库使用。
    • logic:保存处理逻辑源文件,特定项目使用的模块也在此文件夹中保存,并编译成静态链接库使用。
    • gui:保存图形用户接口实现源文件,换言之,程序界面文件,以避免界面和逻辑实现的耦合,是程序的兼容性更强。

其中,src文件夹中包含的所有文件如下:

F:\SMFRAME-WORK-MASTER\SRC
│  Makefile
│  project.pro
│  project.pro.user
│  project.pro.user.01aed67
│  project.pro.user.8ed6e04
│
├─base
│  │  base.h
│  │  base.pro
│  │  base.pro.user
│  │  cprecisetime.cpp
│  │  cprecisetime.h
│  │  Makefile
│  │  Makefile.Debug
│  │  Makefile.Release
│  │  makefilepath.cpp
│  │  makefilepath.h
│  │  object.cpp
│  │  object.h
│  │  state.cpp
│  │  state.h
│  │  thing.cpp
│  │  thing.h
│  │  vardesc.cpp
│  │  vardesc.h
│  │  vardesctable.cpp
│  │  vardesctable.h
│  │  variant.cpp
│  │  variant.h
│  │  variants.cpp
│  │  variants.h
│  │  vsi_pause.cpp
│  │  vsi_pause.h
│  │  vs_idle.cpp
│  │  vs_idle.h
│  │  vs_work.cpp
│  │  vs_work.h
│  │  v_msg.cpp
│  │  v_msg.h
│  │  v_msgqueue.cpp
│  │  v_msgqueue.h
│  │  v_state.cpp
│  │  v_state.h
│  │  v_statemachine.cpp
│  │  v_statemachine.h
│  │
│  ├─debug
│  │      base_pch.obj
│  │      base_pch.pch
│  │      cprecisetime.obj
│  │      makefilepath.obj
│  │      object.obj
│  │      state.obj
│  │      thing.obj
│  │      vardesc.obj
│  │      vardesctable.obj
│  │      variant.obj
│  │      variants.obj
│  │      varmsg.obj
│  │      varmsgqueue.obj
│  │      varstate.obj
│  │      varstatemachine.obj
│  │      varstate_idle.obj
│  │      varstate_pause.obj
│  │      varstate_work.obj
│  │      vsi_pause.obj
│  │      vs_idle.obj
│  │      vs_work.obj
│  │      v_msg.obj
│  │      v_msgqueue.obj
│  │      v_state.obj
│  │      v_statemachine.obj
│  │
│  └─release
├─gui
│  │  cmopenglwidget.cpp
│  │  cmopenglwidget.h
│  │  gui.h
│  │  gui.pro
│  │  gui.pro.user
│  │  main.cpp
│  │  mainwindow.cpp
│  │  mainwindow.h
│  │  mainwindow.ui
│  │  Makefile
│  │  Makefile.Debug
│  │  Makefile.Release
│  │  qtw_varlist.cpp
│  │  qtw_varlist.h
│  │  qw_ball.cpp
│  │  qw_ball.h
│  │  ui_mainwindow.h
│  │
│  ├─debug
│  │      cmopenglwidget.obj
│  │      gui_pch.obj
│  │      gui_pch.pch
│  │      main.obj
│  │      mainwindow.obj
│  │      moc_cmopenglwidget.cpp
│  │      moc_cmopenglwidget.obj
│  │      moc_mainwindow.cpp
│  │      moc_mainwindow.obj
│  │      moc_mvariantslist.cpp
│  │      moc_mvariantslist.obj
│  │      moc_qballwidget.cpp
│  │      moc_qballwidget.obj
│  │      moc_qtw_varlist.cpp
│  │      moc_qtw_varlist.obj
│  │      moc_qw_ball.cpp
│  │      moc_qw_ball.obj
│  │      mvariantslist.obj
│  │      qballwidget.obj
│  │      qtw_varlist.obj
│  │      qw_ball.obj
│  │
│  └─release
└─Logic
    │  logic.h
    │  logic.pro
    │  Logic.pro.user
    │  Makefile
    │  Makefile.Debug
    │  Makefile.Release
    │  vsmt_allsystem.cpp
    │  vsmt_allsystem.h
    │  vsmt_ball.cpp
    │  vsmt_ball.h
    │  vsm_thread.cpp
    │  vsm_thread.h
    │  vsw_allsystem.cpp
    │  vsw_allsystem.h
    │  vsw_ball.cpp
    │  vsw_ball.h
    │
    ├─debug
    │      Logic_pch.obj
    │      Logic_pch.pch
    │      varsm_thread.obj
    │      varsm_thread_allsystem.obj
    │      varsm_thread_ball.obj
    │      varstate_work_allsystem.obj
    │      varstate_work_ball.obj
    │      vsmt_allsystem.obj
    │      vsmt_ball.obj
    │      vsm_thread.obj
    │      vsw_allsystem.obj
    │      vsw_ball.obj
    │
    └─release

makefile文件、obj文件、pch文件pro文件以及*.pro.user均可以通过项目创建或者编译是直接生成,通过IDE菜单命令也可以向pro文件中添加描述代码,以及类的声明和源文件。但部分描述代码需要在Qt中打开手动编译,因此,四个pro项目文件的内容如下所示:

Project.pro

TEMPLATE = subdirs

SUBDIRS += $$PWD/base \
           $$PWD/logic \
           $$PWD/gui

logic.depends=base
gui.depends=logic

该项目文件位于src文件夹下,其内容完全由作者编辑,用于作为子项目目录索引其他项目并配置编译依赖关系,换言之,只需要双击打开该文件就可以浏览所有的三个子项目。该pro文件可以通过IDE中创建空白pro项目菜单命令生成,如下图所示:

创建空白项目

Base.pro

#-------------------------------------------------
#
# Project created by QtCreator 2022-05-05T08:15:13
#
#-------------------------------------------------

QT       += xml

QT       -= gui

TARGET = base
TEMPLATE = lib
CONFIG += staticlib

SOURCES += \
    object.cpp \
    state.cpp \
    thing.cpp \
    vardesc.cpp \
    vardesctable.cpp \
    variant.cpp \
    variants.cpp \
    makefilepath.cpp \
    v_msg.cpp \
    v_msgqueue.cpp \
    v_state.cpp \
    vs_idle.cpp \
    vsi_pause.cpp \
    vs_work.cpp \
    v_statemachine.cpp \
    cprecisetime.cpp

HEADERS += \
    object.h \
    state.h \
    thing.h \
    base.h \
    makefilepath.h \
    vs_idle.h \
    vsi_pause.h \
    vs_work.h \
    v_statemachine.h \
    v_msg.h \
    vardesc.h \
    variant.h \
    vardesctable.h \
    variants.h \
    v_msgqueue.h \
    v_state.h \
    cprecisetime.h
unix {
    target.path = /usr/lib
    INSTALLS += target
}
#-------------------------------------------------
# 额外添加
#-------------------------------------------------
DESTDIR = ../../lib
INCLUDEPATH += ../../includes
PRECOMPILED_HEADER = base.h

在重构过N遍之后的新的项目框架中,作者不再使用windows的ini文件作为项目配置文件(通用性不好,读写速度奇慢,作者做过的大型项目中只能优化到1秒多),而是用xml作为项目的配置文件(兼容性好,读写速度快,相同的项目只需要几十毫秒,且xml文件可以无限添加层级,便于定义变量特性,取值范围,单位之类,非常完美),因此在配置文件中添加QT += xml一行,将DOM(用于解析xml文件)模块包含到项目中(可以直接包含头文件使用),其他文件由IDE创建静态链接库时自动生成,作者在最后添加了三行描述代码,其中:

  • DESTDIR:表示输出文件路径,即生成的base.lib文件输出至lib文件夹中。
  • INCLUDEPATH:表示额外包含的头文件所在文件夹。
  • PRECOMPILED_HEADER:预编译头文件,如果大多数cpp源文件都包含了同一头文件,在编译器预处理之前,先编译该头文件可以极大提升编译速度,类似于windows程序中的stdafx.h文件,只不过QT可以设置预编译文件名称,相对于windows来说就极大的柔性。

该pro文件可以通过IDE中创建C++库项目菜单命令生成,如下图所示:

创建C++库

Logic.pro

#-------------------------------------------------
#
# Project created by QtCreator 2022-05-05T14:46:50
#
#-------------------------------------------------

QT       += xml

QT       -= gui

TARGET = Logic
TEMPLATE = lib
CONFIG += staticlib

SOURCES += \
    vsm_thread.cpp \
    vsmt_allsystem.cpp \
    vsmt_ball.cpp \
    vsw_allsystem.cpp \
    vsw_ball.cpp

HEADERS += logic.h \
    vsm_thread.h \
    vsmt_allsystem.h \
    vsmt_ball.h \
    vsw_allsystem.h \
    vsw_ball.h

unix {
    target.path = /usr/lib
    INSTALLS += target
}

#-------------------------------------------------
# 额外添加
#-------------------------------------------------
DESTDIR = ../../lib
INCLUDEPATH += ../base
INCLUDEPATH += ../../includes
PRECOMPILED_HEADER = logic.h

该项目文件与base.pro类似,但是额外增加了一行INCLUDEPATH += ../base,这表明该项目中的cpp源文件可以直接引用base项目中的头文件,这样文件操作就不用像作者在编译windows项目将所有头文件都复制到include文件夹中。

Gui.pro

#-------------------------------------------------
#
# Project created by QtCreator 2022-05-06T16:38:32
#
#-------------------------------------------------

QT       += core gui
QT       += xml
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = gui
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp \
    qtw_varlist.cpp \
    qw_ball.cpp \
    cmopenglwidget.cpp

HEADERS  += mainwindow.h \
    gui.h \
    qtw_varlist.h \
    qw_ball.h \
    cmopenglwidget.h

FORMS    += mainwindow.ui


win32: LIBS += -L../../lib/ -lbase#$$PWD/

INCLUDEPATH += ../../#$$PWD/
DEPENDPATH += ../../#$$PWD/

win32:!win32-g++: PRE_TARGETDEPS += ../../lib/base.lib#$$PWD/
else:win32-g++: PRE_TARGETDEPS += ../../lib/libbase.a#$$PWD/


win32: LIBS += -L$$PWD/../../lib/ -llogic

INCLUDEPATH += $$PWD/../../
DEPENDPATH += $$PWD/../../

win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../lib/logic.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../lib/liblogic.a



#-------------------------------------------------
# 额外添加
#-------------------------------------------------
DESTDIR = ../../bin
INCLUDEPATH += ../base
INCLUDEPATH += ../logic
INCLUDEPATH += ../../includes
INCLUDEPATH += ../../includes/vld_include
PRECOMPILED_HEADER = gui.h


win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../lib/vld_lib/ -lvld

INCLUDEPATH += $$PWD/../../lib/vld_lib
DEPENDPATH += $$PWD/../../lib/vld_lib

用户界面项目文件大部分的描述代码也由IDE自动生成,这里只需要注意作者手动添加的额外的头文件搜索目录,以及手动添加的vld动态链接库(vld.lib从安装位置拷贝到项目lib/vld_lib文件夹,vld.dll拷贝值bin文件夹下,vld.h拷贝到includes/vld_include文件夹下)用于检测程序退出时的内存泄漏情况。

退出时内存泄漏并不重要,但是其代表这程序可能会出现持续的内存分配而不释放就很重要,这代表着程序运行足够的时间之后就会耗尽内存,导致程序崩溃。

该pro文件可以通过IDE中创建视窗项目菜单命令生成,如下图所示:

创建视窗项目

下一章:讲解作者对变量的通用定义。


         不喜欢 0

D7FECB19D148C1AD1D829F1CD0E23DB0

发表回复

站内搜索

最新评论

归档日历

2024 年 9 月
 1
2345678
9101112131415
16171819202122
23242526272829
30  

标签云