工作过程中,当需要创建很多同一类对象的时候,为了方便管理和维护,通常通过创建一个工厂类,由该工厂类根据不同的参数来创建返回对象,但是在C++中,存在这样的问题,每当新建新的对象的时候,都需要修改工厂类来支持新的对象的创建。从这个过程中,我们可以看出,操作相当繁琐和重复。
基于以上的原因,我们根据头文件定义的类型,使用python来自动创建工厂类文件,同时,将其集成到cmake。所以,每次头文件添加新的类型,那么只需要重新执行cmake来自动更新工厂类文件。
生成文件
假设有如下所示的头文件JMsgDefine.h, 一个枚举值对应一个命令对象,比如接收到E_CMD_ID_LOAD,那么对应的命令类名为JLoadCmd。
有了上面的枚举定义之后,现在就需要实现python文件,命名为JCmdFactory.cpp.py。实现功能函数之前,需要先实现两个支持函数,用于后面函数的调用。
第一个支持函数是get_cmd_id_enum_name_list,该函数的功能是从文件提取枚举名称列表。
第二个支持函数是convert_enum_name_to_class_name,该函数的功能是将枚举名转化为类名,例如E_CMD_ID_LOAD转化为JLoadCmd。
接下来就来说明如何利用python自动生成工厂类文件。一般一个文件通常包含了注释说明、头文件的声明以及函数的实现。所以,就按照这三个步骤来实现自动生成工厂类的python文件。
写入注释
首先实现注释说明的功能函数,该注释主要提示使用者,文件是自动生成的,不能编辑和提交。
写入头文件
然后实现头文件声明的功能函数print_include,它接受两个参数,第一个参数表示文件描述符,第二个参数表示枚举列表值。然后内部函数循环遍历枚举列表,将每个枚举字符串转化为类名,再构建头文件的声明,最后将其写入文件中。
写入函数功能
最后实现将根据枚举值动态创建对象的函数写入文件的功能,print_function同样接收两个参数,其参数功能与print_include是一样的,这里不再重复多说。print_function函数的功能是将创建命令工厂的方法写入文件中。
验证效果
完成python文件JCmdFactory.cpp.py之后,手动执行该python文件,可以看到自动生成了工厂类文件,其内容如下所示:
提取路径
那么如何将python文件集成到cmake呢,首先需要说明正则表达式的几个用法,然后再详细说明将python集成到cmake的方法。
总结列出正则表达式几个关键符号的含义
12等符号
1、2等需要和正则表达式()一起使用才行。比如1表示重复第一个()匹配到的内容, 2表示重复第二个()匹配到的内容,以此类推。
比如正则表达式“^(123)(456)21$ ”, 那么字符串“123456456123”,则能够被正则表达式匹配到。
解析路径
假设现在有如下路径“the/picture/ACmd.cpp.py”, 那么如何提取目录和CPP文件呢?
如果想要提取目录,那么输入正则表达式”^(.+/).+.py”, 则符号()匹配到的字符串为“the/picture/”。注意.py前面的符号“”, 是转义符号,表示.不作为关键符号处理。
如果想要提取CPP文件,那么输入正则表达式“^(.+).py”, 则符号()匹配到的字符串为“the/picture/ACmd.cpp”
自动调用
下面列出嵌入到cmake文件中自动调用python文件的代码段。
现在一一解释cmake关键字的功能含义
file是递归查找${PROJECT_SOURCE_DIR}/*.py匹配到的所有文件,然后存储到PY_FILES。PROJECT_SOURCE_DIR是cmake内置的定义,表示工程源代码目录。
string则利用正则表达式来提取目录和文件,string的结构如下图所示。正则表达式的含义上一节已经说明了。这里有一个需要注意的是”1″, 它的功能就是正则表达式中的”1″, 那么为什么会多出一个“”, 个人理解符号“”也是cmake的关键符号,所以需要先转义一层。
execute_process则是执行提取到的python文件。
总结
本文首先基于python,实现了从枚举类型中提取创建对象,然后自动生成工厂类文件的python文件,接着将实现的python文件集成到cmake中,从而在编译代码时,自动生成工厂类文件,因此,解决了创建相似代码的重复性动作的问题。