本帖最后由 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);
|