使用成员函数作为回调

art*_*.sw 0 c++ callback static-members

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

glfwSetCursorPosCallback(window, (GLFWcursorposfun)(MyClass::mouseButtonChanged));
Run Code Online (Sandbox Code Playgroud)

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

但是我能做什么?

Bar*_*rry 5

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

void (*)(GLFWindow*, double, double)
Run Code Online (Sandbox Code Playgroud)

不幸的是,它们似乎没有为您提供任何类型的上下文论证的位置。所以一种方法是全局回调方法:

struct MyCallback {
    static MyClass* obj;

    static void callback(GLFWindow* window, double a, double b) {
        obj->mouseButtonChanged(window, double a, double b);
    }
};
Run Code Online (Sandbox Code Playgroud)

像这样使用:

MyCallback::obj = &myObj;
glfwSetCursorPosCallback(window, &MyCallback::callback);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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


小智 5

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

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

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

你不能使用常规方法作为回调,因为GLFW是一个C库,不知道对象和这个指针.如果希望接收到C++对象的回调,请使用静态方法或常规函数作为回调,将指向您希望调用的对象的指针存储为窗口的用户指针,并使用它来调用对象上的方法.