使用成员函数作为回调

时间:2015-02-02 17:52:40

标签: c++ callback static-members

我想使用成员函数作为回调(使用this function):

glfwSetCursorPosCallback(window, (GLFWcursorposfun)(MyClass::mouseButtonChanged));

我知道这是不可能的,因为我需要一个MyClass的实例来调用方法mouseButtonChanged

但我该怎么办?

2 个答案:

答案 0 :(得分:5)

您可以使用glfwSetWindowUserPointer附加管理窗口的C ++类。之后,您可以编写一个静态函数转发到'WindowManager'的成员函数

来自http://www.glfw.org/faq.html#how-do-i-use-c-methods-as-callbacks

  

2.16 - 如何使用C ++方法作为回调?

     

您不能使用常规方法作为回调,因为GLFW是C库   并且不知道对象和这个指针。如果你愿意的话   接收回调到C ++对象,使用静态方法或常规方法   作为回调函数,将指针存储到您想要的对象   调用窗口的用户指针并使用它来调用方法   你的对象。

答案 1 :(得分:4)

您需要传入此类型的函数指针:

void (*)(GLFWindow*, double, double)

不幸的是,看起来他们没有给你任何上下文参数的位置。因此,一种方法是全局回调方法:

struct MyCallback {
    static MyClass* obj;

    static void callback(GLFWindow* window, double a, double b) {
        obj->mouseButtonChanged(window, double a, double b);
    }
};

用作:

MyCallback::obj = &myObj;
glfwSetCursorPosCallback(window, &MyCallback::callback);

这是有效的,因为callback现在不需要实例。不幸的是,现在我们有一个全球MyClass*。尽管如此,我们仍然坚持这一点。我们不能在这里使用std::bind()表达式或lambda,因为任何带有捕获的东西都不能转换为函数指针。

[更新]由于您可以在void*上添加window,因此您也可以这样做:

glfwSetWindowUserPointer(window, &myObj);
glfwSetCursorPosCallback(window, +[](GLFWindow* win, double a, double b){
    static_cast<MyClass*>(glfwGetWindowUserPointer(win))->mouseButtonChanged(win, a, b);
});

没有捕获的lambda上的operator+(例如本例中的那个)将其转换为原始函数指针。