一、准备
1、创建一个lvdiv.c文件
在创建新的文件的同时,要在CMakeLists.txt里加入文件名
二、构建对象
1、 定义类型的字典
STATIC const mp_rom_map_elem_t lv_div_locals_dict_table[] ={}
2、把字典转换成对象
STATIC MP_DEFINE_CONST_DICT(lv_div_locals_dict, lv_div_locals_dict_table);
3、定义类结构
const mp_obj_type_t lv_type_div = {
{ &mp_type_type}, // 必须以这个开头
.name = MP_QSTR_div, // 类的名字(注意大小写)
.locals_dict = (mp_obj_dict_t *)&lv_div_locals_dict, // 添加类成员字典
.make_new = lv_div_make_new, // 构造函数
};
4、构造函数
STATIC mp_obj_t lv_div_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_div_t *self = m_new_obj(lv_div_t); // *
self->base.type = &lv_type_div; // 必须设置返回值的类型 // *
// 父级对象
if(n_args>0 && mp_obj_get_type(args[0]) == &lv_type_div){
printf("确认是父级\n");
self->parent = (lv_div_t *)args[0];
}
return MP_OBJ_FROM_PTR(self); // *
}
5、在 lv_mod.h 里定义数据类型
// 定义DIV结构体
struct _lv_div_t{
mp_obj_base_t base; // 每个 Micropython 类必须以这个开始
int16_t x;
int16_t y;
uint32_t width;
uint32_t height;
lv_div_t *parent;
};
6、构建成员方法
// 1. 分别获得 x,y , width ,height
// 2. positon, size
// 3. box(x, y, w, h)
// STATIC mp_obj_t lv_div_px(mp_obj_t self_in, mp_obj_t value){
// MP_DEFINE_CONST_FUN_OBJ_2
STATIC mp_obj_t lv_div_px(size_t n_args, const mp_obj_t *args){
lv_div_t *self = (lv_div_t *)args[0];
if(n_args>1 && &mp_type_int == mp_obj_get_type(args[1])){
// 赋值
self->x = mp_obj_get_int(args[1]);
}
return mp_obj_new_int(self->x);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lv_div_px_obj,1,2,lv_div_px);
STATIC mp_obj_t lv_div_py(size_t n_args, const mp_obj_t *args){
mp_arg_check_num(n_args,0,1,2,false);
lv_div_t *self = (lv_div_t *)args[0];
if(n_args>1 && &mp_type_int == mp_obj_get_type(args[1])){
// 赋值
self->y = mp_obj_get_int(args[1]);
}
return mp_obj_new_int(self->y);
}
MP_DEFINE_CONST_FUN_OBJ_VAR(lv_div_py_obj,1,lv_div_py);
/**
* @brief 设置位置
* 传入两个或者一个参数表设置,不传参表示获取
* (x, y)
* (x)
* ((x,y))
* ([x,y])
* () =>(x,y)
*/
STATIC mp_obj_t lv_div_position(size_t n_args, const mp_obj_t *args){
lv_div_t *self = (lv_div_t *)args[0];
if(n_args>1){
// 设置
// 1 个int
// 2 个 int
// 1 元组
if(2 == n_args ){ // 表示传入一个参数
if(&mp_type_int == mp_obj_get_type(args[1])){ // 只设置 x
self->x = mp_obj_get_int(args[1]);
}else if(&mp_type_tuple == mp_obj_get_type(args[1])){
mp_obj_tuple_t *t = args[1];
if(t->len==1){ // 只传入了一个值
self->x = mp_obj_get_int(t->items[0]);
}else if(t->len>1){
self->x = mp_obj_get_int(t->items[0]);
self->y = mp_obj_get_int(t->items[1]);
}
}
}else if(n_args>2){
if(&mp_type_int == mp_obj_get_type(args[1]) && &mp_type_int == mp_obj_get_type(args[2])){
self->x = mp_obj_get_int(args[1]);
self->y = mp_obj_get_int(args[2]);
}
}
return MP_OBJ_FROM_PTR(self);
}else{
mp_obj_t pos_table[2]; // 创造元组都数组
pos_table[0] = mp_obj_new_int(self->x); // 设置元组元素
pos_table[1] = mp_obj_new_int(self->y);
mp_obj_tuple_t *pos = mp_obj_new_tuple(2,pos_table); // 创造一个元组
return MP_OBJ_FROM_PTR(pos);
}
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lv_div_position_obj,1,3,lv_div_position);
STATIC mp_obj_t lv_div_size(size_t n_args, const mp_obj_t *args){
lv_div_t *self = (lv_div_t *)args[0];
if(n_args>1){ // 设置
// 设置
// 1 个int
// 2 个 int
// 1 元组
if(2 == n_args ){ // 表示传入一个参数
if(&mp_type_int == mp_obj_get_type(args[1])){ // 只设置 x
self->width = mp_obj_get_int(args[1]);
}else if(&mp_type_tuple == mp_obj_get_type(args[1])){
mp_obj_tuple_t *t = args[1];
if(t->len==1){ // 只传入了一个值
self->width = mp_obj_get_int(t->items[0]);
}else if(t->len>1){
self->width = mp_obj_get_int(t->items[0]);
self->height = mp_obj_get_int(t->items[1]);
}
}
}else if(n_args>2){
if(&mp_type_int == mp_obj_get_type(args[1]) && &mp_type_int == mp_obj_get_type(args[2])){
self->width = mp_obj_get_int(args[1]);
self->height = mp_obj_get_int(args[2]);
}
}
return MP_OBJ_FROM_PTR(self);
}else{
mp_obj_t pos_table[2]; // 创造元组都数组
pos_table[0] = mp_obj_new_int(self->width); // 设置元组元素
pos_table[1] = mp_obj_new_int(self->height);
mp_obj_tuple_t *pos = mp_obj_new_tuple(2,pos_table); // 创造一个元组
return MP_OBJ_FROM_PTR(pos);
}
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lv_div_size_obj,1,3,lv_div_size);
并将成员方法加入到字典里
STATIC const mp_rom_map_elem_t lv_div_locals_dict_table[] ={
{ MP_ROM_QSTR(MP_QSTR_DEFAULT_WIDTH), MP_ROM_INT(200)},
{ MP_ROM_QSTR(MP_QSTR_px), MP_ROM_PTR(&lv_div_px_obj)},
{ MP_ROM_QSTR(MP_QSTR_py), MP_ROM_PTR(&lv_div_py_obj)},
{ MP_ROM_QSTR(MP_QSTR_position), MP_ROM_PTR(&lv_div_position_obj)},
{ MP_ROM_QSTR(MP_QSTR_sizet), MP_ROM_PTR(&lv_div_size_obj)},
};
三、构建对象的子对象
1、新建一个 lvspan.c 的文件
并在 CMakeLists.txt 里加上新建的文件名
2、 定义子类型的字典
STATIC const mp_rom_map_elem_t lv_span_locals_dict_table[]={};
3、将字典转换成对象
STATIC MP_DEFINE_CONST_DICT(lv_span_locals_dict, lv_span_locals_dict_table);
4、定义子类的结构
const mp_obj_type_t lv_type_span = {
{ &mp_type_type}, // 必须以这个开头
.name = MP_QSTR_span, // 类的名字(注意大小写)
.locals_dict = (mp_obj_dict_t *)&lv_span_locals_dict, // 添加类成员字典
.make_new = lv_span_make_new, // 构造函数
.attr = call_parent_methods, // 暴露父类方法
.parent = &lv_type_div,
};
.attr = call_parent_methods, // 暴露父类方法
可以调用父类的成员方法:
void call_parent_methods(mp_obj_t obj, qstr attr, mp_obj_t *dest)
{
const mp_obj_type_t *type = mp_obj_get_type(obj);
while (type->locals_dict != NULL) {
// generic method lookup
// this is a lookup in the object (ie not class or type)
assert(type->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now
mp_map_t *locals_map = &type->locals_dict->map;
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
if (elem != NULL) {
mp_convert_member_lookup(obj, type, elem->value, dest);
break;
}
if (type->parent == NULL) {
break;
}
// search parents
type = type->parent;
}
}
.parent = &lv_type_div :将 lvdiv 作为 lvspand 的父类
4、构建函数
STATIC mp_obj_t lv_span_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args){
lv_span_t *self = m_new_obj(lv_span_t);
self->base.base.type = type;
// 父级对象
if(n_args>0 && mp_obj_get_type(args[0]) == &lv_type_div){
printf("确认是父级\n");
self->base.parent = (lv_div_t *)args[0];
}
return MP_OBJ_FROM_PTR(self);
}
5、在 lv_mod.h 里定义数据类型
// 继承自 DIV 的类
struct _lv_span_t{
lv_div_t base;
uint32_t color;
};