-
When I use C to extend MicroPython, I hope to create two classes, which are inheritance relationships. The implementation method in Python is: class A:
def x():
return 10;
def y():
return 20;
class B(A):
def width():
return 230;
def height():
return 480; The types in C are: const mp_rom_map_elem_t &class_a_local_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&class_a_x_obj) },
{ MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&class_a_y_obj) },
};
const mp_obj_type_t class_a_type = {
{ &mp_type_type },
.name = MP_QSTR_A,
.make_new = &class_a_make_new,
.locals_dict = (mp_obj_dict_t *)&class_a_local_dict,
};
const mp_rom_map_elem_t &class_b_local_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&class_b_width_obj) },
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&class_b_height_obj) },
};
const mp_obj_type_t class_b_type = {
{ &mp_type_type },
.name = MP_QSTR_B,
.make_new = &class_b_make_new,
.locals_dict = (mp_obj_dict_t *)&class_b_local_dict,
.parent = &class_a_type,
}; But if it's the way C is written, the result is that when I
When the return content is
But if it is
If class inheritance is written in Python, it is not the result. How should I solve this problem? The result I want is
This is the result of Python class inheritance (Edited by @jimmo to add formatting) |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 3 replies
-
MicroPython does not support inheritance of native classes. The typical way this is solved is to duplicate the entries in the locals dict. This means that So in your case: (Note: I've also added in the missing
There is a further code size optimisation possible here where they can both share the same locals dict table (but still separate dicts):
See |
Beta Was this translation helpful? Give feedback.
-
I've already taken care of it, I feel at ease now~~ const mp_obj_type_t class_b_type = {
{ &mp_type_type },
.name = MP_QSTR_B,
.make_new = &class_b_make_new,
.locals_dict = (mp_obj_dict_t *)&class_b_local_dict,
.parent = &class_a_type,
.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;
}
} |
Beta Was this translation helpful? Give feedback.
-
I required parental inheritance for native classes, and using @Mars-CN answer as a base, came up with a function that could be used directly for a static void mp_obj_parent_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_type_t * type = (mp_obj_type_t *)mp_obj_get_type(self_in);
while (type != NULL || type != &mp_type_object) {
if (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) {
mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(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_obj_t result = elem->value;
if (mp_obj_is_obj(result)) {
const mp_obj_type_t *m_type = ((mp_obj_base_t *)MP_OBJ_TO_PTR(result))->type;
if (m_type->flags & MP_TYPE_FLAG_BINDS_SELF) {
dest[0] = mp_obj_new_bound_meth(result, self_in);
return;
}
}
mp_convert_member_lookup(MP_OBJ_NULL, type, result, dest);
return;
}
}
type = (mp_obj_type_t *)MP_OBJ_TYPE_GET_SLOT(type, parent);
}
} @jimmo Is there a particular reason why there is the assumption why native classes can not inherit from native classes? |
Beta Was this translation helpful? Give feedback.
I've already taken care of it, I feel at ease now~~
It's actually very simple, just fill in the attr element, as follows: