You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派陀螺仪程序报错:无法将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 07:30:15