• 用python的mako模板库写一个自动生成.c/.h文件generate_code功能


    需求:最近组里有这样一个需求,大概就是用代码生成代码(这里的代码指的是C代码,其中有一大部分是重复的格式)。实际工作当中,如果手动自行去复制-->粘贴-->修改-->调试,大概率会调试不通过,问题多半出现在'修改'这个一环节。比如有时候少粘贴个';' ,这样的小失误会徒增我们码农的麻烦(最重要的是不能早点下班~~哈哈),所以这个小程序就出来了。

     

    一 、准备工作

    • python基础
    • xlwings,这个是关于excel表格数据的处理库
    • mako,模板引擎,用来做模子的。
    • thinker,可以做一个简单的界面,将程序打成.exe给你的C猿使用。

    二 、思路

    • 整体分为三步,打开冰箱,把大象放进去,关上。。。不好意思,跑题了。
    1. c猿朋友,给我一个excel(3),里面有一些像java里的entity的东西,我们不管它是什么
    2. 然后我要给他,长的像这样(4)的.h/.c文件
    3. 名称变量代码信号名称信号值描述变量代码类型
      idvar_codesignal_namesignal_commentvar_type
      0x387TBOX_Satellite_Time_Hour小时0x0:0int8_t
      0x387TBOX_SatelliteTime_Minute分钟0x17:23 0x0:0 0x3B:59int8_t
      1. #ifndef __X_APP_CAN_H
      2. #define __X_APP_CAN_H
      3. #include "typedef.h"
      4. #include "stdint.h"
      5. #include "stdbool.h"
      6. enum {
      7. CAN_TX_ENABLE_NOSEND = 0,
      8. CAN_TX_ENABLE_SEND,
      9. CAN_TX_DISABLE,
      10. };
      11. enum {
      12. CAN_BUS_STAT_NORMAL = 0,
      13. CAN_BUS_STAT_BUSOFF_FAST,
      14. CAN_BUS_STAT_BUSOFF_SLOW,
      15. };
      16. typedef struct
      17. {
      18. uint8_t rx_flag;
      19. int32_t time;
      20. int8_t TBOX_Satellite_Time_Hour;
      21. int8_t TBOX_SatelliteTime_Minute;
      22. }TCU_DATA_0x387_t;
      23. extern TCU_DATA_0x387_t TCU_DATA_0x387;
      24. typedef struct
      25. {
      26. uint8_t rx_flag;
      27. int32_t time;
      28. int8_t TBOX_SatelliteTime_Minute;
      29. }TCU_DATA_0x999_t;
      30. extern TCU_DATA_0x999_t TCU_DATA_0x999;
      31. void app_can_data_init(void);
      32. void app_can_proc(void);
      33. void can_send_proc(void);
      34. uint16_t app_speed_get_speed_cm();

    到这里,比较长的朋友应该看出来,这个东西不就是java里的实体嘛,然后我们的需求就像mybatis-plus 里的generateCode功能一样,当然这个他的这个功能比较完善,entity,dao,service,controller,还有mapper这些一套东西都有,搞java的同学应该很熟悉这些。所以,现在我们要做的是用python做个一个简单的generateCode。

    仔细看,应该能看到h文件里的实体,动态的的字段有一个或者多个。

    int8_t TBOX_Satellite_Time_Hour;
    int8_t TBOX_SatelliteTime_Minute;

    还有实体的名字也是变量

    typedef struct
    {
        uint8_t rx_flag;
        int32_t time;
        int8_t TBOX_Satellite_Time_Hour;
        int8_t TBOX_SatelliteTime_Minute;
    }TCU_DATA_0x387_t;
    extern TCU_DATA_0x387_t TCU_DATA_0x387;

    看到这里,我想个位小天才也有思路了。

    • 我是这么想的先从excel表格提取数据格式是json数组这样子

            [{'id': '0x387', 'var_code': 'TBOX_Satellite_Time_Hour'},

            {'id': '0x387', 'var_code': 'TBOX_SatelliteTime_Minute'}]  ;

    • 然后利用python的mako模板库,写一个模板文件.mako  ,这个文件主要是控制生成的c文件格式样式的,模板文件就长下面这样 ;
      1. enum {
      2. CAN_BUS_STAT_NORMAL = 0,
      3. CAN_BUS_STAT_BUSOFF_FAST,
      4. CAN_BUS_STAT_BUSOFF_SLOW,
      5. };
      6. % for item in entitys:
      7. typedef struct
      8. {
      9. uint8_t rx_flag;
      10. int32_t time;
      11. % for record in item['records']:
      12. ${record['var_type']} ${record['var_code']};
      13. % endfor
      14. }TCU_DATA_${item['id']}_t;
      15. extern TCU_DATA_${item['id']}_t TCU_DATA_${item['id']};
      16. % endfor

    • 最后,把json数据渲染到模板文件.mako

    三 、撸

    代码我就直接贴出来了

    1. import xlwings as xw
    2. from mako.template import Template
    3. from win32com.client import DispatchEx
    4. ''' 1,读取excel中的sheet,返回多个sheet列表'''
    5. def read_excel(excel):
    6. xl = xw._xlwindows.COMRetryObjectWrapper(DispatchEx("Ket.Application"))
    7. impl = xw._xlwindows.App(visible=False, add_book=False, xl=xl)
    8. app = xw.App(visible=False, add_book=False, impl=impl)
    9. wb = app.books.open(excel)
    10. sht = wb.sheets[0]
    11. # wb.save()
    12. wb.close()
    13. # app.quit()
    14. app.kill()
    15. return sht
    16. ''' 2,解析sheet,提取 entity 数据信息封装成dic'''
    17. # [{'id': '0x387', 'var_code': 'TBOX_Satellite_Time_Hour'},{'id': '0x387', 'var_code': 'TBOX_SatelliteTime_Minute'}]
    18. def parse_excel(sheet):
    19. titles_comm = sheet.range('A1').options(expand='right').value
    20. titels = sheet.range('A2').options(expand='right').value
    21. entitys = []
    22. for row in sheet.range('A3').expand('table').value:
    23. entity = dict(zip(titels, row))
    24. entitys.append(entity)
    25. return entitys
    26. ''' 通过ID 和并一些数据 ,返回list'''
    27. def merge_data_by_id(l: list):
    28. t = {}
    29. for d in l:
    30. if d['id'] not in t:
    31. t[d['id']] = {k: d.get(k, []) for k in ('id', 'records')}
    32. t[d['id']]['records'].append({k: d[k] for k in ('var_code', 'var_type', 'signal_name')})
    33. return t.values()
    34. ''' 3.根据mako模板生成.h/.c文件'''
    35. def generate_code_h(entitys: list):
    36. datas = {'entitys': entitys}
    37. h_file = Template(filename='./mako_template/entity_h.mako', module_directory='./mako_template/tmp').render(
    38. **datas)
    39. with open('./generate_file/entity_h.h', 'wb+') as f:
    40. f.write(h_file.encode('utf-8'))
    41. print('h_file 文件生成,成功 @——@')
    42. if __name__ == '__main__':
    43. excel = 'C:\\Users\\15839680585\\Desktop\\template\\Desktop\\entity2.xlsx'
    44. sht = read_excel(excel)
    45. # 读取excel数据,然后封装为json
    46. l = parse_excel(sht)
    47. l_entity = merge_data_by_id(l)
    48. print(l_entity)
    49. generate_code_h(l_entity)

    四 、坑

    • 在用xlwings的时候,如果电脑上装的是wps就会遇到插件不能用,像我这样写就应该没问题
    • 在.mako模板文件中取字典dic某个key的值时候,不要${dic.key},正确的是${dic['key']}
    • 对了xlwings使用的时候有wb.close(),app.quit()这样的关闭操作,我这一直报错,也没搞懂不管了,所以我就把他注释了,暂时还能运行,希望懂得大佬指点下。

     写在最后,水平有限,请大佬们指导~ 最重要的是希望能帮助到像我这样到处查资料的人~

  • 相关阅读:
    SpringBoot实现多线程
    C++QT开发——Xml、Json解析
    Flutter学习4-基本UI组件
    远程办公或常态化,“小城房”or“大城床”你会怎么选?
    【C#设计模式】单例模式
    骨传导耳机低频差理所当然?飞利浦A6606表示不服
    5个超好用的视频素材网站,视频剪辑必备。
    C语言趣味代码(三)
    C++多态案例-设计计算器类
    token、cookie、session
  • 原文地址:https://blog.csdn.net/cai__niao__/article/details/132620468