首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >指向作为类成员的函数- GLFW setKeycallback

指向作为类成员的函数- GLFW setKeycallback
EN

Stack Overflow用户
提问于 2011-10-06 23:50:36
回答 5查看 26.2K关注 0票数 36

我正在编写一个GLFW应用程序,在其中我已经将函数调用封装到一个简单的类中。我在设置密钥回调时遇到问题。我的类被定义为:

代码语言:javascript
复制
class GAME 
{
private:
    bool running;
public:
    GAME();
    int execute();
    void events(int, int);
    int loop();
    int render();
};

execute函数为:

代码语言:javascript
复制
int GAME::execute() 
    {
        glfwOpenWindow(640, 320, 8, 8, 8, 8, 0, 0, GLFW_WINDOW);
        glfwSetWindowTitle("Viraj");
        glfwSetKeyCallback(events);
        running = true;
        while(glfwGetWindowParam(GLFW_OPENED))
        {
            glfwPollEvents();
            loop();
            render();
        }
        return 0;
    }

在Visual Studio 2010上编译以下代码会出现错误:

error C3867: 'GAME::events': function call missing argument list; use '&GAME::events' to create a pointer to member

使用&GAME::events可以提供:

error C2664: 'glfwSetKeyCallback' : cannot convert parameter 1 from 'void (__thiscall GAME::* )(int,int)' to 'GLFWkeyfun' 1> There is no context in which this conversion is possible

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-10-07 00:05:54

有一种用于指向类成员方法的C++语法,但您不能将它们传递给C风格的应用程序接口。C理解函数调用和每个非静态对象方法,以您的events为例,在C术语中看起来就像这样:void events(void* this, int, int);意味着除了标准参数之外,每个方法都会得到一个this指针,而不是静默地传递。

要使您的events C兼容,请将其设置为static void events(int, int);。这样,它将遵循C语言的调用语义--它不需要传递this指针。您还必须以某种其他方式将您的对象传递给此回调(如果您需要在回调中包含此对象的数据)。

票数 20
EN

Stack Overflow用户

发布于 2015-02-23 01:09:56

其他答案中提供的代码示例没有描述如何将回调重定向到每个对象的成员函数,其中可能包含任意数量的对象。让你的类成为单例会限制你的设计,并且不会扩展到多个glfw窗口。

可伸缩的解决方案是将glfw窗口用户指针设置为您的对象,然后在回调中获取它,并调用成员函数:

代码语言:javascript
复制
class MyGlWindow
{
public:
     void mouseButtonPressed();
};

void makeWindow()
{
    GLFWwindow* glfwWindow;
    MyGlWindow* myWindow;

    /* ... Initialize everything here ... */

    glfwSetWindowUserPointer(glfwWindow, myWindow);

    auto func = [](GLFWwindow* w, int, int, int)
    {
        static_cast<MyGlWindow*>(glfwGetWindowUserPointer(w))->mouseButtonPressed( /* ... */ );
    }

    glfwSetMouseButtonCallback(glfwWindow, func);
}

此解决方案更短,适用于任何数量的窗口。

票数 61
EN

Stack Overflow用户

发布于 2016-12-12 02:46:51

我也有同样的问题,在阅读了这篇文章后,我想出了一个类似的解决方案。我觉得这样会更干净一点。它基于静态函数,但它嵌套在我们设置所有内容的类中。

Header如下所示:

代码语言:javascript
复制
class Application
    {
    public:
        ...
    private:
        ...
        void MousePositionCallback(GLFWwindow* window, double positionX, double positionY);
        void KeyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
        ...
        class GLFWCallbackWrapper
        {
        public:
            GLFWCallbackWrapper() = delete;
            GLFWCallbackWrapper(const GLFWCallbackWrapper&) = delete;
            GLFWCallbackWrapper(GLFWCallbackWrapper&&) = delete;
            ~GLFWCallbackWrapper() = delete;

            static void MousePositionCallback(GLFWwindow* window, double positionX, double positionY);
            static void KeyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
            static void SetApplication(Application *application);
        private:
            static Application* s_application;
        };
    };

和源代码:

代码语言:javascript
复制
void Application::GLFWCallbackWrapper::MousePositionCallback(GLFWwindow* window, double positionX, double positionY)
{
    s_application->MousePositionCallback(window, positionX, positionY);
}

void Application::GLFWCallbackWrapper::KeyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    s_application->KeyboardCallback(window, key, scancode, action, mods);
}

void Application::GLFWCallbackWrapper::SetApplication(Application* application)
{
    GLFWCallbackWrapper::s_application = application;
}

Application* Application::GLFWCallbackWrapper::s_application = nullptr;

void Application::MousePositionCallback(GLFWwindow* window, double positionX, double positionY)
{
    ...
}

void Application::KeyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    ...
}

void Application::SetCallbackFunctions()
{
    GLFWCallbackWrapper::SetApplication(this);
    glfwSetCursorPosCallback(m_window, GLFWCallbackWrapper::MousePositionCallback);
    glfwSetKeyCallback(m_window, GLFWCallbackWrapper::KeyboardCallback);
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7676971

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档