Lv_indev_drv how to set read_cb when the function is member of a class?

I am afraid my C++ is too rusty and this is a pure C++ problem. But I figured someone in here must have an easy answer in here.

I am setting up my input like this:

void Input::begin(lv_group_t *_focusGroup) {
    indev_ButtonsDriver.type = LV_INDEV_TYPE_ENCODER;
    indev_ButtonsDriver.read_cb = readButtons;
    indev_ButtonsEncoder = lv_indev_drv_register(&indev_ButtonsDriver);
    lv_indev_set_group(indev_ButtonsEncoder, _focusGroup);

where readButtons is a function: bool Input::readButtons(lv_indev_drv_t * indev, lv_indev_data_t * data).

I get this error:

cannot convert 'Input::readButtons' from type 'bool (Input::)(lv_indev_drv_t*, lv_indev_data_t*) {aka bool (Input::)(_lv_indev_drv_t*, lv_indev_data_t*)}' to type 'bool (*)(_lv_indev_drv_t*, lv_indev_data_t*)'

I am not entirely surprised to be honest. But as I said in the beginning, my C++ is very rusty and while I can make a sense for what this means I am completely clueless as to how to solve the problem.
Any advice would be greatly appreciated!
thank you!

Reverse your thinking.
Have a shim of a global static function call your class instance’s method.


Ok the problem is now more clear. So the solution is to have a static global function that is aware of my classes instance call the function of this instance and just pass the pointers in the arguments?

Yup, that is the jist! This can also be referred to as “thunking”.

Ok, thanks, I think I understand the concept. I still fail at implementation. The idea is to create the instance and call begin() in my main file, and not having to do anything related to lvgl there. But it seems this is not possible?
Like I’d need to do something like this:

Input inputInstance;
inputInstance.indev_Buttonsdriver.read_cb = inputInstance.readButtons;

Wouldn’t this be quite an ugly solution? I’ve tried passing the function as an argument to begin(), but I’m getting rather obvious compiler errors :roll_eyes:

Any chance somebody could give me an example on how this is supposed to look like when properly coded?

Never said it would be pretty! :slight_smile:

Input inputInstance;

static bool my_input_read(lv_indev_drv_t * drv, lv_indev_data_t* data) {
  return inputInstance.readButtons(drv, data);

void setup() {
  lv_indev_drv_t indev_drv;
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  indev_drv.read_cb = my_input_read;