本帖最后由 aple0807 于 2021-9-26 16:36 编辑
在单片机的C语言项目中,会大量采用结构体来封装操作对象数据模型,然后用指针传入函数来处理数据。
当系统中创建多个操作对象,且模型有多个处理函数时,直接调用函数处理结构体,可读性将会变差,且书写不方便,我已经深受其害,总是书写混淆。
此时如果引入C++中对象成员函数的方式来调用接口,可读性将会大幅提高,也会极大降低书写错误率。
下面举例阐述C结构对象操作的方法,仅适用于全局对象操作。
例如我们使用的内存管理,当系统中有SRAM,SDRAM,CCM等地址不连续的内存需要管理时。
我们创建如下结构来描述内存。
mem_alloc.h文件- // 对象运行信息
- typedef struct
- {
- uu8 init_ok;
- uu16 used_block;
- } multi_malloc_info_type;
- // 对象API成员
- typedef struct
- {
- void * (*malloc)(size_t size);
- void * (*calloc)(size_t num, size_t size);
- void * (*realloc)(void *, size_t size);
- void(*free)(void *);
- uu16(*perused)(void);
- } multi_malloc_api_type;
- // 对象结构
- typedef struct
- {
- uu64 *mem; // 内存基址
- uu16 *mem_tab; // 分配表
- uu16 mem_size; // 内存尺寸
- uu16 block_size; // 块大小-分配单位
- uu16 block_amount; // 块数量
- uu16(*lock)(void); // 互斥锁请求
- void(*unlock)(void); // 互斥锁释放
- multi_malloc_info_type *info; // 运行信息-必要
- const multi_malloc_api_type *api; // 对象接口-可选
- } multi_malloc_type;
下面函数操作内存,
mem_alloc.c文件
- void multi_malloc_init(const multi_malloc_type*obj)
- {
- };
- void * multi_malloc(const multi_malloc_type*obj, size_t size)
- {
- };
- void * multi_calloc(const multi_malloc_type*obj, size_t num, size_t size)
- {
- };
- void * multi_realloc(const multi_malloc_type*obj, void *, size_t size)
- {
- };
- void multi_free(const multi_malloc_type*obj, void *)
- {
- };
- uu16 multi_malloc_perused(const multi_malloc_type *obj)
- {
- };
通常我们直接调用这里的函数来操作对象,
比如 :
multi_free(&obj_sram, ptr);
multi_free(&obj_ccram, ptr);
当程序中有很多这种写法时,往往会搞错对象,造成很隐蔽的错误难以发现。
为了让程序看起来更加简单明了,我们将这一组函数进行封装,然后挂载到对象结构的.api成员上。
方法如下:
使用宏创建一组函数,配置内存时将函数列表连接在结构体的 .api变量上。
这里实际是要创建一个 multi_malloc_api_type 变量,内容是名字为 “obj”的函数成员
mem_alloc.c文件++
- #define multi_malloc_api_name(obj) &obj##_api
- #define multi_malloc_api_ref(obj) const multi_malloc_api_type obj##_api
- #define multi_malloc_api_link(obj) obj.api=obj##_api // 非const结构使用
- #define multi_malloc_api_make(obj) \
- void * obj##_malloc(size_t size){return multi_malloc(&obj, size);} \
- void * obj##_calloc(size_t num, size_t size) \
- {return multi_calloc(&obj, num, size);} \
- void * obj##_realloc(void *p, size_t size) \
- {return multi_realloc(&obj, p, size);} \
- void obj##_free(void *p){ multi_free(&obj, p);} \
- uu16 obj##_perused(void){ return multi_malloc_perused(&obj);} \
- const multi_malloc_api_type obj##_api = { \
- obj##_malloc, \
- obj##_calloc, \
- obj##_realloc, \
- obj##_free, \
- obj##_perused \
- }
创建对象
该步骤用于生成一个具体可操作的对象,可以创建多个。
mem_alloc.c文件++
- uu64 sram_map[1024 / 8] @".sram"; // 内存池
- uu16 sram_tab[32] @".sram"; // 内存分配表
- multi_malloc_info_type sram_info = { 0 }; // 工作信息
- uu16 sram_lock(void)
- {
- return 0;
- }
- // 申请互斥锁
- void sram_unlock(void)
- {
- }
- // 释放互斥锁
- multi_malloc_api_ref(mem_sram); // 接口引用声明
- const multi_malloc_type mem_sram = // 信息描述
- {
- sram_map,
- sram_tab,
- sizeof(sram_map),
- 32,
- sizeof(sram_map) / 32,
- sram_lock,
- sram_unlock,
- &sram_info,
- multi_malloc_api_name(mem_sram) // 关联到API
- };
- multi_malloc_api_make(mem_sram); // 创建API接口
应用程序中可以如下方法使用对象接口,这样程序书写可以借助编辑器的自动补全功能,书写十分方便
- extern const multi_malloc_type mem_sram;
- ptr = mem_sram.api->malloc(100);
- mem_sram.api->free(ptr);
|