树莓派陀螺仪程序报错:无法将Gyro对象传入回调函数
问题描述
正在开发树莓派与加速度计/陀螺仪的交互程序,需要高频更新陀螺仪数据,因此设置定时执行的更新逻辑。现有代码如下:
void updateGyro(Gyro gyro) { gyro.update(); } int main() { if (gpioInitialise() < 0) return -1; // 创建Gyro对象 Gyro gyro; // 设置定时器每10毫秒执行一次更新 gpioSetTimerFuncEx(0, 10, updateGyro, &gyro); time_sleep(10); gpioTerminate(); }
运行时报错:
gyro.cpp: In function ‘int main()’: gyro.cpp:113:31: error: invalid conversion from ‘void (*)(Gyro)’ to ‘gpioTimerFuncEx_t’ {aka ‘void (*)(void*)’} [-fpermissive] 113 | gpioSetTimerFuncEx(0, 10, updateGyro, &gyro); | ^~~~~~~~~~ | | | void (*)(Gyro) In file included from gyro.cpp:2: /usr/include/pigpio.h:3751:55: note: initializing argument 3 of ‘int gpioSetTimerFuncEx(unsigned int, unsigned int, gpioTimerFuncEx_t, void*)’ 3751 | unsigned timer, unsigned millis, gpioTimerFuncEx_t f, void *userdata); | ~~~~~~~~~~~~~~~~~~^
尝试直接传入gyro.update也无法解决,求修复方案。
函数文档翻译
gpioSetTimerFuncEx ------------------ int gpioSetTimerFuncEx(unsigned timer, unsigned millis, gpioTimerFuncEx_t f, void *userdata) 功能:设置指定编号的定时器,每隔指定毫秒数调用一次目标函数,并将用户数据指针作为参数传递给该函数。 参数: - timer:定时器编号(范围0-9) - millis:触发间隔(单位毫秒,最小值为1) - f:回调函数,需符合`void (*)(void*)`签名,即接收一个void*类型参数的无返回值函数 - userdata:传递给回调函数的用户自定义数据指针 返回值:成功返回0;失败时返回对应错误码:PI_BAD_TIMER(无效定时器编号)、PI_BAD_MILLIS(无效间隔值)或PI_BAD_FUNC(无效函数指针)
修复方案
错误核心是回调函数签名不匹配:gpioSetTimerFuncEx要求回调接收void*类型参数,但你的updateGyro接收Gyro值类型参数,且值传递会创建对象副本,导致无法修改原对象数据。
修复代码(全局函数回调)
// 修正回调函数签名,适配void*参数 void updateGyro(void* userdata) { // 将void*转换为Gyro指针,确保操作原对象 Gyro* gyro = static_cast<Gyro*>(userdata); if (gyro != nullptr) { gyro->update(); } } int main() { if (gpioInitialise() < 0) return -1; Gyro gyro; // 传入修正后的回调函数与原对象地址 gpioSetTimerFuncEx(0, 10, updateGyro, &gyro); time_sleep(10); gpioTerminate(); }
修复代码(类成员函数回调)
若想用Gyro类的成员函数作为回调,需用静态成员函数做包装(成员函数隐含this指针,无法直接作为C风格回调):
class Gyro { public: void update() { // 原陀螺仪更新逻辑 } // 静态成员函数作为回调包装 static void updateCallback(void* userdata) { Gyro* gyro = static_cast<Gyro*>(userdata); if (gyro != nullptr) { gyro->update(); } } }; int main() { if (gpioInitialise() < 0) return -1; Gyro gyro; // 传入静态成员函数与原对象地址 gpioSetTimerFuncEx(0, 10, Gyro::updateCallback, &gyro); time_sleep(10); gpioTerminate(); }
内容的提问来源于stack exchange,提问作者Bartlomiej Dlugosz
相关产品推荐
相关产品推荐

