访问C++类中的C风格回调

caf*_*ine 0 c c++ pointers member-function-pointers callback

PiGPIO库提供以下C风格的API函数:

typedef void (*gpioAlertFuncEx_t)(int, int, uint32_t, void *);  // assumed  
int gpioSetAlertFuncEx(unsigned user_gpio, gpioAlertFuncEx_t f, void *userdata)
Run Code Online (Sandbox Code Playgroud)

基本上它允许您通过回调函数处理引脚状态更改.

到现在为止还挺好.问题是将此回调包装到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;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是回调函数类型不同(因为它是非静态的).并且提示错误:

 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 );
Run Code Online (Sandbox Code Playgroud)

诀窍是什么?如何投射&PushButton::internal_gpio_callback以匹配所需的模板?

稍后编辑:我不想让回调方法静态.

Som*_*ude 5

指向一个成员函数是相同的一个指针指向一个非成员函数.不同之处在于成员函数需要调用对象,这是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;
    }
};
Run Code Online (Sandbox Code Playgroud)