在 C++ 中访问 C 风格的回调 class
Accessing C-style callbacks inside C++ class
PiGPIO 库提供了以下 C 风格的 API 函数:
typedef void (*gpioAlertFuncEx_t)(int, int, uint32_t, void *); // assumed
int gpioSetAlertFuncEx(unsigned user_gpio, gpioAlertFuncEx_t f, void *userdata)
基本上它允许您通过回调函数处理引脚状态更改。
到目前为止一切顺利。问题是将此回调包装到 c++ class.
我的方法如下:
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
以匹配所需的模板?
稍后编辑:我不想将回调方法设为静态。
指向成员函数的指针与指向非成员函数的指针不同。不同之处在于成员函数需要调用一个对象,这是 C 无法处理的。
有很多方法可以解决这个问题,特别是在您已经将 this
作为 userdata
指针传递的情况下。解决方案是简单地将真正的成员函数包装在 static 成员函数中(因为它们可以作为 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;
}
};
PiGPIO 库提供了以下 C 风格的 API 函数:
typedef void (*gpioAlertFuncEx_t)(int, int, uint32_t, void *); // assumed
int gpioSetAlertFuncEx(unsigned user_gpio, gpioAlertFuncEx_t f, void *userdata)
基本上它允许您通过回调函数处理引脚状态更改。
到目前为止一切顺利。问题是将此回调包装到 c++ class.
我的方法如下:
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
以匹配所需的模板?
稍后编辑:我不想将回调方法设为静态。
指向成员函数的指针与指向非成员函数的指针不同。不同之处在于成员函数需要调用一个对象,这是 C 无法处理的。
有很多方法可以解决这个问题,特别是在您已经将 this
作为 userdata
指针传递的情况下。解决方案是简单地将真正的成员函数包装在 static 成员函数中(因为它们可以作为 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;
}
};