[C语言] C 结构变量对象化操作

[复制链接]
 楼主| aple0807 发表于 2021-9-26 16:40 | 显示全部楼层 |阅读模式
本帖最后由 aple0807 于 2021-9-26 16:36 编辑

在单片机的C语言项目中,会大量采用结构体来封装操作对象数据模型,然后用指针传入函数来处理数据。
当系统中创建多个操作对象,且模型有多个处理函数时,直接调用函数处理结构体,可读性将会变差,且书写不方便,我已经深受其害,总是书写混淆。
此时如果引入C++中对象成员函数的方式来调用接口,可读性将会大幅提高,也会极大降低书写错误率。

下面举例阐述C结构对象操作的方法,仅适用于全局对象操作。
例如我们使用的内存管理,当系统中有SRAM,SDRAM,CCM等地址不连续的内存需要管理时。

我们创建如下结构来描述内存。

mem_alloc.h文件
  1. // 对象运行信息
  2. typedef struct
  3. {
  4.     uu8 init_ok;
  5.     uu16 used_block;
  6. } multi_malloc_info_type;


  7. // 对象API成员
  8. typedef struct
  9. {
  10.     void * (*malloc)(size_t size);
  11.     void * (*calloc)(size_t num, size_t size);
  12.     void * (*realloc)(void *, size_t size);
  13.     void(*free)(void *);
  14.     uu16(*perused)(void);
  15. } multi_malloc_api_type;

  16. // 对象结构
  17. typedef struct
  18. {
  19.     uu64 *mem;                            // 内存基址
  20.     uu16 *mem_tab;                        // 分配表
  21.     uu16 mem_size;                        // 内存尺寸
  22.     uu16 block_size;                    // 块大小-分配单位
  23.     uu16 block_amount;                    // 块数量
  24.     uu16(*lock)(void);                    // 互斥锁请求
  25.     void(*unlock)(void);                // 互斥锁释放
  26.     multi_malloc_info_type *info;        // 运行信息-必要
  27.     const multi_malloc_api_type *api;    // 对象接口-可选
  28. } multi_malloc_type;



下面函数操作内存,
mem_alloc.c文件
  1. void multi_malloc_init(const multi_malloc_type*obj)
  2. {
  3. };
  4. void * multi_malloc(const multi_malloc_type*obj, size_t size)
  5. {
  6. };
  7. void * multi_calloc(const multi_malloc_type*obj, size_t num, size_t size)
  8. {
  9. };
  10. void * multi_realloc(const multi_malloc_type*obj, void *, size_t size)
  11. {
  12. };
  13. void multi_free(const multi_malloc_type*obj, void *)
  14. {
  15. };
  16. uu16 multi_malloc_perused(const multi_malloc_type *obj)
  17. {
  18. };


通常我们直接调用这里的函数来操作对象,
比如 :
multi_free(&obj_sram, ptr);
multi_free(&obj_ccram, ptr);
当程序中有很多这种写法时,往往会搞错对象,造成很隐蔽的错误难以发现。
为了让程序看起来更加简单明了,我们将这一组函数进行封装,然后挂载到对象结构的.api成员上。

方法如下:        
使用宏创建一组函数,配置内存时将函数列表连接在结构体的 .api变量上。
这里实际是要创建一个 multi_malloc_api_type 变量,内容是名字为 “obj”的函数成员
mem_alloc.c文件++
  1. #define multi_malloc_api_name(obj)    &obj##_api
  2. #define multi_malloc_api_ref(obj)    const multi_malloc_api_type  obj##_api
  3. #define multi_malloc_api_link(obj)    obj.api=obj##_api    // 非const结构使用

  4. #define multi_malloc_api_make(obj)                                        \
  5.     void * obj##_malloc(size_t size){return multi_malloc(&obj, size);}    \
  6.     void * obj##_calloc(size_t num, size_t size)                          \
  7.             {return multi_calloc(&obj, num, size);}                       \
  8.     void * obj##_realloc(void *p, size_t size)                            \
  9.             {return multi_realloc(&obj, p, size);}                        \
  10.     void obj##_free(void *p){ multi_free(&obj, p);}                       \
  11.     uu16 obj##_perused(void){ return multi_malloc_perused(&obj);}         \
  12.     const multi_malloc_api_type  obj##_api = {                            \
  13.         obj##_malloc,                                                     \
  14.         obj##_calloc,                                                     \
  15.         obj##_realloc,                                                    \
  16.         obj##_free,                                                       \
  17.         obj##_perused                                                     \
  18.     }


创建对象
该步骤用于生成一个具体可操作的对象,可以创建多个。

mem_alloc.c文件++
  1. uu64 sram_map[1024 / 8] @".sram";            // 内存池
  2. uu16 sram_tab[32] @".sram";                  // 内存分配表
  3. multi_malloc_info_type sram_info = { 0 };    // 工作信息
  4. uu16 sram_lock(void)
  5. {
  6.     return 0;
  7. }               
  8. // 申请互斥锁
  9. void sram_unlock(void)
  10. {
  11. }                    
  12. // 释放互斥锁
  13. multi_malloc_api_ref(mem_sram);               // 接口引用声明
  14. const multi_malloc_type mem_sram =            // 信息描述
  15. {
  16.     sram_map,
  17.     sram_tab,
  18.     sizeof(sram_map),
  19.     32,
  20.     sizeof(sram_map) / 32,
  21.     sram_lock,
  22.     sram_unlock,
  23.     &sram_info,
  24.     multi_malloc_api_name(mem_sram)           // 关联到API
  25. };
  26. multi_malloc_api_make(mem_sram);              // 创建API接口



应用程序中可以如下方法使用对象接口,这样程序书写可以借助编辑器的自动补全功能,书写十分方便
  1. extern const multi_malloc_type mem_sram;

  2. ptr = mem_sram.api->malloc(100);
  3. mem_sram.api->free(ptr);




您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

326

帖子

2

粉丝
快速回复 返回顶部 返回列表