External C modules & root pointers support #9962
Replies: 3 comments 1 reply
-
Option 2 ( Frustratingly, when you write So if the struct had been declared typedef struct lv_layout_dsc_t {
....
} lv_layout_dsc_t; Then you could have written typedef struct {
...
} lv_layout_dsc_t; so no dice. One option would be to do this in your user module C code: typedef struct lvgl_root_pointers_t {
lv_layout_dsc_t *_lv_layout_list;
} lvgl_root_pointers_t;
MP_REGISTER_ROOT_POINTER(struct lvgl_root_pointers_t * lvgl); and then heap-allocate the root pointers struct. This is basically what the NimBLE bindings do. The disadvantage is that you now spend an extra word of .bss, but the advantage is that the RAM for the pointers isn't used unless you use LVGL. (Note that you must heap-allocate the root pointers struct, it can't be in .bss itself, because the GC won't search it -- it only follows heap pointers) |
Beta Was this translation helpful? Give feedback.
-
Ah yes, at one point I had wrapped so the lvgl pointers on a new struct (actually a new micropython type) that meant there was only one struct that needed to be registered globally, but then figured that anyone actually compiling lvgl into their codebase is going to be using it, so I shouldn't need to worry about not using ram if it's not used. Wrapping it in that way to allow cleaner registration (without just void*) is nice though, and better than needing to wrap each pointer in the list with individual casting access macros. |
Beta Was this translation helpful? Give feedback.
-
@andrewleech @jimmo I followed this discussion but got into a situation where callbacks are still being garbage collected. I use Zephyr with modified LVGL to expose The application interprets single script at startup:
LVGL is initialized with The application runs and timers work until first GC execution, then it crashes with bus fault within
However, shouldn't |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I've been working on some minor refactoring of the lvgl library to support building with the standard External C Module system.
The library / module compiled has a number of global variables that are dynamically allocated when running a
lvgl_init()
function on first use. These are currently stored / tracked as root pointers, now registered with the new #define eg.These then make their way into
build/genhdr/root_pointers.h
which is then included in themp_state_vm_t
struct inpy/mpstate.h
However, this throws compile issues because
py/mpstate.h
doesn't #include any of the (external c module specific) headers to declare thelv_layout_dsc_t
etc types.For my initial proof of concept PR linked above, I hacked around this with
CFLAGS_USERMOD += -include "lvgl/lvgl.h"
for stm32 / unix builds, but don't know if/how this is possible with cmake builds - it's not ideal either way.I've had some thoughts on alternative options, not sure of the best course forward though?
new define to add includes
Add a
#define MP_REGISTER_ROOT_POINTER_INCLUDE
that is parsed by the same root pointers genhdr to create an header file to be #include'd inpy/mpstate.h
. Not really my preferred approach, seems pretty heavy handed for something that's not been needed before? But perhaps quite flexible?register as
void*
Register all the root pointers like
MP_REGISTER_ROOT_POINTER(void*_lv_layout_list);
to avoid the need of includes, then cast them to the correct type somewhere else in the external C module for use within lvgl.don't use root pointers, attach to module itself
This would really be my preferred approach; the lvgl module that's created allocates these objects during an init function, it would arguably be better if they were just attached to the module itself rather than directly in global root pointers table. However currently, the module is CONST declared in flash so can't have new attributes attached.
Eventually I want to make this module work as a native mpy as well; in this case the module is always dynamically created in the
mpy_init()
function at which point these pointers could be allocated and attached to the module itself - perfect!I'm wondering if there's some way we could create a similar
mpy_init()
function that's run-on-import for compiled-in user C modules that could then be a common system for both native and external c modules?Beta Was this translation helpful? Give feedback.
All reactions