I believe @amirgon has recommended that one avoids user_data in MicroPython code. You don’t need it since you can pass anything that’s callable as a callback. Here is an example of how to implement what you want using lambdas.
Probably I’m over complicating it and thinking to C-ish, but the full scenario is to store arbitrary data (the a array in the example) in some objects and get them them later. In C I added an event handler and passed the pointer to the custom data as user_data. And with a custom event code, e.g. LV_EVENT_GET_MY_DATA I set it in the event parameter. Like:
Do you want to attach some data to an LVGL object?
Or do you want to pass context to a callback?
To pass some extra context to an event handler, the simplest way is to use a lambda as explained above. This allows you to pass any number of arguments to the event callback function (arguments which you set when you add the event callback).
If you want to “assign” some values to an LVGL object, the simplest way is to inherit from the LVGL object and add members to your derived objects. For a derived object to keep its identity you need to set user_data to point to the derived object instead of the base object.
Then you can use btn.additional_data anywhere, also in an event callbacks. (Online example)
(if you don’t set user_data in MyBtn constructor it will still work, but when calling evt.get_target() you would get the parent lv.btn instead of MyBtn and you will not have access to your data members)
We use this technique today when creating custom widgets in Micropython: