【问题标题】:Use non-member method as a callback in GLUT [duplicate]在 GLUT 中使用非成员方法作为回调 [重复]
【发布时间】:2013-02-13 23:39:07
【问题描述】:

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

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

当我将此函数移动到专门处理键盘相关函数的类(KeyBoardMovement)时,它似乎不起作用:

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

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

我不明白这个错误,因为我看不出放置在不同位置的相同函数之间有什么区别。

【问题讨论】:

    标签: c++ oop opengl


    【解决方案1】:

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

    因此,您可以像这样制作一个全局 shim 函数:

    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 映射到您的全局数据。然后,您可以采用与上述类似的方法来获得特定于窗口的数据。

    【讨论】:

    • 我在spec 中没有看到任何提及glutSetWindowData()。你确定这不是 FreeGLUT 或 OpenGLUT 扩展吗?
    • 该死,它是一个 OpenGLUT 扩展。手册页没有说清楚。文档确实说,一个可行的替代方法是维护您自己的从窗口 ID 到成员数据的映射,这很容易使用 std::map 完成。
    【解决方案2】:

    C++ 不支持闭包,这意味着它不能将一个类实例连同一个方法一起变成一个函数指针,当被调用时将执行该类实例的方法。

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

    【讨论】:

      猜你喜欢
      • 2011-07-19
      • 1970-01-01
      • 1970-01-01
      • 2013-01-17
      • 1970-01-01
      • 1970-01-01
      • 2021-03-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多