Доступ к обратным вызовам в стиле C внутри класса C ++ - PullRequest
0 голосов
/ 28 сентября 2018

Следующая библиотека API в стиле C предоставлена ​​библиотекой PiGPIO:

typedef void (*gpioAlertFuncEx_t)(int, int, uint32_t, void *);  // assumed  
int gpioSetAlertFuncEx(unsigned user_gpio, gpioAlertFuncEx_t f, void *userdata)

В основном она позволяет обрабатывать изменение состояния вывода с помощью функции обратного вызова.

Пока все хорошо,Проблема заключается в переносе этого обратного вызова в класс c ++.

Мой подход заключается в следующем:

class Pin
{
public:
    Pin(_GpioPin)
    {
        gpioSetAlertFuncEx(_GpioPin, &PushButton::internal_gpio_callback, this );
    }

    void internal_callback_func(int pin, int level, uint32_t tick)
    {
        cout << "New level: " << pin << " " << level;
    }
}

Проблема заключается в том, что тип функции обратного вызова отличается (потому что он нестатический).И выдается ошибка:

 error: cannot convert 'void (Pin::*)(int, int, uint32_t, void*) {aka void (Pin::*)(int, int, unsigned int, void*)}' to 'gpioAlertFuncEx_t {aka void (*)(int, int, unsigned int, void*)}' for argument '2' to 'int gpioSetAlertFuncEx(unsigned int, gpioAlertFuncEx_t, void*)'
  gpioSetAlertFuncEx(this->GpioPin, &Pin::internal_gpio_callback), this );

В чем прикол?Как привести &PushButton::internal_gpio_callback в соответствие с требуемым шаблоном?

Позднее редактирование: я не хочу делать метод обратного вызова статическим.

1 Ответ

0 голосов
/ 28 сентября 2018

Указатель на функцию-член не такой же, как указатель на функцию, не являющуюся членом.Разница в том, что функция-член нуждается в вызове объекта, чего не может обработать C.

Есть способы обойти это, особенно в вашем случае, когда вы уже передаете this как userdata указательРешение состоит в том, чтобы просто обернуть реальную функцию-член в статическую функцию-член (поскольку они могут быть переданы как функции обратного вызова C).

Например:

class Pin
{
public:
    Pin(_GpioPin)
    {
        gpioSetAlertFuncEx(_GpioPin, &Pin::static_internal_callback_func, this );
    }

private:
    static void static_internal_callback_func(int pin, int level, uint32_t tick, void* userdata)
    {
        static_cast<Pin*>(userdata)->internal_callback_func(pin, level, tick);
    }

    void internal_callback_func(int pin, int level, uint32_t tick)
    {
        cout << "New level: " << pin << " " << level;
    }
};
...