STATIC mp_obj_t myfont(mp_obj_t path_obj) {
char *path = mp_obj_str_get_str(path_obj);
FILE *fp = fopen(path, 'rb');
lv_font_t myf = init_my_font(fp);
return ???;
}
What should I put in ???
STATIC mp_obj_t myfont(mp_obj_t path_obj) {
char *path = mp_obj_str_get_str(path_obj);
FILE *fp = fopen(path, 'rb');
lv_font_t myf = init_my_font(fp);
return ???;
}
What should I put in ???
I tried including lv_mpy.c and using ptr_to_mp
, but lots of errors emerged.
Hi @TsXor !
Could you give us some more details on what you are trying to do?
What’s the goal in your case to initialize the font in C? You could read it from file in pure Python if you want.
In general, if you would like to automatically generate Micropython API for your C functions, the simplest way is to:
When building lv_micropython, lvgl.h
is scanned and Micropython API is automatically generated. So if you extend lvgl.h with your new API, you could use it later through the lvgl module.
Another more advanced option is to auto-generate a new Micropython module from your API.
As an example you can look at mkrules.cmake which auto generates Micropython API for parts of the ESP-IDF.
It is a dynamic module so it cannot use C functions of lvgl.
However I eventually managed to do it:
include lvgl.h
define a C function binded to python, getting callback functions and python class object at python side.
STATIC mp_obj_t assembler(mp_obj_t font_type, mp_obj_t dsc_cb, mp_obj_t bmp_cb)
assembler(font_t, dsc_cb, bmp_cb)
mp_lv_struct_t
from lv_mpy_example.c
typedef struct mp_lv_struct_t
{
mp_obj_base_t base;
void *data;
} mp_lv_struct_t;
struct my_dsc {
mp_obj_t dsc_cb;
mp_obj_t bmp_cb;
};
lv_font_t
at C side, put the struct in step 4 to the dsc
struct my_dsc *dsc = (struct my_dsc *)m_malloc(sizeof(struct my_dsc));
dsc->dsc_cb = dsc_cb; dsc->bmp_cb = bmp_cb;
lv_font_t *lv_font_obj = (lv_font_t *)m_malloc(sizeof(lv_font_t));
lv_font_obj->dsc = dsc;
bool get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) {
mp_obj_t args[1]; args[0] = mp_obj_new_int(unicode_letter);
mp_obj_t size_obj = mp_call_function_n_kw(((struct my_dsc *)font->dsc)->dsc_cb, 1, 0, args);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(size_obj, &bufinfo, MP_BUFFER_READ);
struct sizetup *size = bufinfo.buf;
dsc_out->adv_w = size->w; /*Horizontal space required by the glyph in [px]*/
dsc_out->box_h = size->h; /*Height of the bitmap in [px]*/
dsc_out->box_w = size->w; /*Width of the bitmap in [px]*/
dsc_out->ofs_x = 0; /*X offset of the bitmap in [pf]*/
dsc_out->ofs_y = 0; /*Y offset of the bitmap measured from the as line*/
dsc_out->bpp = 8; /*Bits per pixel: 1/2/4/8*/
return true;
}
const uint8_t * get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter) {
mp_obj_t args[1]; args[0] = mp_obj_new_int(unicode_letter);
mp_obj_t bmp_obj = mp_call_function_n_kw(((struct my_dsc *)font->dsc)->bmp_cb, 1, 0, args);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(bmp_obj, &bufinfo, MP_BUFFER_READ);
uint8_t *bitmap = bufinfo.buf;
return bitmap;
}
lv_font_t
in C lv_font_obj->get_glyph_dsc = get_glyph_dsc_cb;
lv_font_obj->get_glyph_bitmap = get_glyph_bitmap_cb;
mp_lv_struct_t
from lv_font_t
. mp_obj_base_t *tbase = (mp_obj_base_t *)m_malloc(sizeof(mp_obj_base_t));
tbase->type = (mp_obj_type_t *)font_type;
mp_lv_struct_t *pyf = (mp_lv_struct_t *)m_malloc(sizeof(mp_lv_struct_t));
pyf->base = *tbase;
pyf->data = lv_font_obj;
That’s why it is needed to get the lvgl.font_t
object from python side: dynamic module cannot use static C things defined in lvgl, but we can get it in python and pass it to C.
return (mp_obj_t)pyf;
I’m writing a “font engine” as a dynamic module so that I don’t need to recompile the whole firmware