使用非静态成员函数为 glfw 设置回调函数

问题描述 投票:0回答:1

我正在使用 glfw 来设置 OpenGL 可视化。我想将回调函数设置为非静态函数来访问类变量。但是,当我执行以下操作时,出现错误“必须调用对非静态成员函数的引用”。我知道在这种情况下回调函数必须是静态的,但有没有办法实现目标?

class Viewer
{
public:
    Viewer()
    {
        glfwSetErrorCallback(errorCallback);
    }

private:

    void errorCallback(int error, const char* description)
    {
        // print more class variables
        std::cerr << "Error: " << description << std::endl;
    }

};
c++ callback glfw
1个回答
0
投票

GLFW 是C 接口,不支持C++ 对象。对于窗口、监视器和操纵杆回调函数,您可以为这些对象中的每一个存储一个用户指针,在回调函数中检索它,并使用它来调用对象的成员函数(方法)。

错误回调是不可能的。相反,您可以使用全局变量来存储指向本地错误处理程序的指针。如果此变量不是

nullptr
,则全局错误回调将调用此错误处理程序。你在调用 GLFW 函数之前设置这个指针,然后恢复它或使它无效。

请注意,这种简单的方法仅适用于单线程应用程序。如果您从多个线程调用 GLFW 函数,则需要确保线程安全。 GLFW 4 可能会对此进行改进。

我的 C++ 很生疏,所以不要指望它开箱即用,但我相信它展示了你可以做什么:

typedef void (*glfw_error_handler_function)(void* user_data, int error_code, const char* description);

thread_local static struct glfw_error_handler_t {
    void* user_data;
    glfw_error_handler_function handler;
} glfw_error_handler = { NULL, NULL };

static void global_glfw_error_handler(int error_code, const char* description) {
    if (glfw_error_handler.handler != NULL) {
        glfw_error_handler.handler(glfw_error_handler.user_data, error_code, description);
    }
}

class Window {
private:
    GLFWwindow* window;
    
    void errorCallback(int error, const char* description) {
        std::cerr << "Error: " << description << std::endl;
    }
public:
    Window() {
        window = glfwCreateWindow();
        // error handling omitted for simplicity
    }
    
    void requestAttention() {
        glfw_error_handler_t previousState = glfw_error_handler;
        glfw_error_handler.user_data = this;
        glfw_error_handler.handler = Window::errorCallback;
        
        glfwRequestWindowAttention(window);
        
        // Restore previous error handler state
        glfw_error_handler = previousState;
    }
}

static int main() {
    glfwSetErrorCallback(global_glfw_error_handler);

    if (!glfwInit()) {
        return EXIT_FAILURE;
    }

    Window window();
    window.requestAttention();

    return 0;
}

另一种可能性是在全局错误处理程序中抛出 C++ 错误,并在调用有问题的 GLFW 函数的位置捕获它。

© www.soinside.com 2019 - 2024. All rights reserved.