创建结构体类型
在代码中,首先定义了一个名为 lv_obj_t
的结构体类型,并在该结构体中定义了坐标、大小和父级对象等基本属性
struct _lv_obj_t{
mp_obj_base_t base; // 必须以这个开头
int16_t x;
int16_t y;
uint32_t width;
uint32_t height;
lv_obj_t *parent;
};
创建字典表
使用 STATIC const mp_rom_map_elem_t
定义了一个名为 lv_obj_locals_dict_table
的字典表,该字典表为空。
// 定义 lv_obj_t 类型的字典
STATIC const mp_rom_map_elem_t lv_obj_locals_dict_table[] = {};
利用宏定义将字典表转换成对象
使用 MP_DEFINE_CONST_DICT
宏定义将字典表转换成对象 lv_obj_locals_dict
。
// 把字典转换成对象
STATIC MP_DEFINE_CONST_DICT(lv_obj_locals_dict, lv_obj_locals_dict_table);
创造类类型对象
使用 STATIC const mp_obj_type_t
定义了一个名为 lv_type_obj
的类型对象。该类型对象包含类型信息、类名、类成员字典、构造函数和父类等属性。其中,构造函数为 lv_obj_make_new
。
// 定义 lv_type_obj 类型对象
STATIC const mp_obj_type_t lv_type_obj = {
{ &mp_type_type }, // 类型信息
.name = MP_QSTR_obj, // 类名
.locals_dict = (mp_obj_dict_t *)&lv_obj_locals_dict, // 类成员字典
.make_new = lv_obj_make_new, // 构造函数
.parent = NULL, // 父类
};
创造构造函数
定义了一个名为 lv_obj_make_new
的构造函数。该构造函数接受一个参数列表,解析出父级对象,并分配内存空间并返回一个 mp_obj_t
对象。
// 定义 lv_obj_make_new 构造函数
STATIC mp_obj_t lv_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args){
// 检查参数
mp_arg_check_num(n_args, n_kw, 0, 1, false);
// 分配内存空间
lv_obj_t *self = m_new_obj(lv_obj_t);
self->base.type = type; // 指定数据类型
// 解析参数
if(n_args > 0 && &lv_type_obj == mp_obj_get_type(args[0])){
self->parent = (lv_obj_t *)args[0];
}
return MP_OBJ_FROM_PTR(self); // 返回对象
}
代码总览
(包含所创建的所有方法和类)
STATIC mp_obj_t lv_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
typedef struct _lv_obj_t lv_obj_t;//改名
// 1. 定义类型的字典
STATIC const mp_rom_map_elem_t lv_obj_locals_dict_table[] = {};
// 2. 把字典转换成对象
STATIC MP_DEFINE_CONST_DICT(lv_obj_locals_dict, lv_obj_locals_dict_table);
// 3. 定义类结构
STATIC const mp_obj_type_t lv_type_obj = {
{ &mp_type_type }, // 类类型定义
.name = MP_QSTR_obj, // 类名
.locals_dict = (mp_obj_dict_t *)&lv_obj_locals_dict, // 类成员字典
.make_new = lv_obj_make_new,
.parent = NULL,
};
// 5. 定义数据类型
struct _lv_obj_t{
mp_obj_base_t base; // 必须以这个开头
int16_t x;
int16_t y;
uint32_t width;
uint32_t height;
lv_obj_t *parent;
};
// 4. 定义构造函数(类型,按位置传递参数数量,按字典传递参数熟练,参数列表)
STATIC mp_obj_t lv_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args){
// 可以传入一个参数,i也可以不传入参数
// 传入得参数就是父级标签
printf("调用了构造方法,传入%d个参数\n", n_args);
// 检查参数(按位置参数得数量,按字典参数的数量,最参数要求,最大参数要求,是否允许按字典传值)
mp_arg_check_num(n_args, n_kw, 0, 1, false);
// m_malloc(sizeof(lv_obj_t));
lv_obj_t *self = m_new_obj(lv_obj_t); // 开辟类空间(SELF)
self->base.type = type; // 制定数据类型(非常重要)
// self->base.type = &lv_type_obj;
if(n_args >0 && &lv_type_obj == mp_obj_get_type(args[0])){
printf("确定是父级对象\n");
self->parent = (lv_obj_t *)args[0];
}
return MP_OBJ_FROM_PTR(self); // 返回对象
}
// ################################## 第一步 添加模块 ##################################
// 1. 创建模块字典 MP_QSTR_ __name__
STATIC const mp_rom_map_elem_t lvgl_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_lvgl) }, // 模块的名称
// 方法定义的3. 加入到字典中
{ MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&lv_print_obj) }, // 无参数方法
{ MP_ROM_QSTR(MP_QSTR_hello), MP_ROM_PTR(&lv_hello_obj) }, // 带一个参数的方法
{ MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&lv_add_obj) }, // 带两个参数的方法
{ MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&lv_append_obj) }, // 带两个参数的方法
// 静态常量
{ MP_ROM_QSTR(MP_QSTR_INTVALUE), MP_ROM_INT(100)},
{ MP_ROM_QSTR(MP_QSTR_BOOLVALUE), MP_ROM_FALSE},
// 类型定义
{ MP_ROM_QSTR(MP_QSTR_obj), MP_ROM_PTR(&lv_type_obj) },
{ MP_ROM_QSTR(MP_QSTR_div), MP_ROM_PTR(&lv_type_div) },
{ MP_ROM_QSTR(MP_QSTR_span), MP_ROM_PTR(&lv_type_span) },
{ MP_ROM_QSTR(MP_QSTR_ashan), MP_ROM_PTR(&lv_type_ashan) },
};
// 2. 将元素数组转换成字典对象
STATIC MP_DEFINE_CONST_DICT(lvgl_globals, lvgl_globals_table); // 转换成字典对象
// 3. 定义模块
const mp_obj_module_t mp_mod_lvgl = {
.base = { &mp_type_module }, // 类型指向(模块的类型恒定为 &mp_type_module)
.globals = (mp_obj_dict_t *)&lvgl_globals, // 指向字典
};
// 4. 注册模块到系统
MP_REGISTER_MODULE(MP_QSTR_lvgl, mp_mod_lvgl);