使用非静态成员功能设置GLFW的回调功能

发布于 2025-02-13 02:14:38 字数 437 浏览 0 评论 0原文

我正在使用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;
    }

};

I'm using glfw for setting up the OpenGL visualization. I would like to set the callback function as non-static function to access the class variables. However, when I did below I got the error "reference to non-static member function must be called". I know that the callback function must be static in this case, but is there a way to achieve the objective?

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

private:

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

};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

じее 2025-02-20 02:14:39

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功能。

GLFW is a C interface, and does not support C++ objects. For the window, monitor and joystick callback functions, you can store a user pointer for each of these objects, retrieve it in the callback functions, and use that to call a member function (method) of your objects.

This is not possible with the error callback. Instead, you can use a global variable to store a pointer to a local error handler. The global error callback calls this error handler if this variable is not a nullptr. You set this pointer before calling a GLFW function, and restore it or nullify it afterwards.

Note that this simple approach only works for single-threaded applications. If you are calling GLFW functions from multiple threads, you need to ensure the thread safety. GLFW 4 will likely improve upon this.

My C++ is very rusty, so don't expect this to work out of the box, but I believe it demonstrates what you can do:

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;
}

Another possibility may be to throw a C++ error in the global error handler, and catch it at the location that calls the offending GLFW function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文