使用非成员方法作为GLUT中的回调

Use non-member method as a callback in GLUT

本文关键字:GLUT 回调 成员方法      更新时间:2023-10-16

我正试图将一个函数传递给GLUT回调glutSpecialFunc。

当我试图将一个静态函数(specialKeyProcessor)传递给它时,它工作得很好

当我把这个函数移到一个专门处理键盘相关函数的类(KeyBoardMovement)上时,它似乎不起作用:

键盘移动键盘;。。。。glutSpecialFunc(keyboard.specialKeyProcessor);

弹出错误:必须调用对非静态成员函数的引用。

我不理解这个错误,因为我看不出同一个函数放在不同的地方有什么区别。

glutSpecialFunc函数设置每个窗口的回调。如果您使用OpenGLUT,它还允许您使用glutSetWindowData将一些数据与每个窗口关联起来。

因此,您可以制作这样的全局填充函数:

void specialKeyProcessor(int key, int x, int y) {
    KeyboardMovement *keyboard = static_cast<KeyboardMovement *>(glutGetWindowData());
    keyboard->specialKeyProcessor(key, x, y);
}

并使用glutGetWindowData:关联您的键盘处理程序

glutSetWindowData(static_cast<void *>(&keyboard));

如果需要存储多个窗口数据,可以存储一个指向特定于窗口的struct的指针,该指针包含每个特定于窗口数据的字段。


如果您不使用OpenGLUT,可以考虑使用std::map将窗口ID映射到全局数据。然后,您可以采用与上面类似的方法来获得特定于窗口的数据。

C++不支持闭包,这意味着它不能将类实例和方法一起转换为函数指针,当被调用时,函数指针将执行类实例的方法。

不幸的是,GLUT不像大多数其他C回调API那样支持数据感知回调。因此,它要么编写一个包装函数,它将调用类的全局实例,要么使用一个名为"ffcall"的库来使用一些非常肮脏的技巧,它实际上可以在运行时创建新的函数,这些函数可以被参数化,并作为一个可以传递给GLUT的闭包。但这真的很黑暗,正确的做法是抛弃GLUT。