我正在编写一个GLFW应用程序,在其中我已经将函数调用封装到一个简单的类中。我在设置密钥回调时遇到问题。我的类被定义为:
class GAME
{
private:
bool running;
public:
GAME();
int execute();
void events(int, int);
int loop();
int render();
};
execute函数为:
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
发布于 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
指针。您还必须以某种其他方式将您的对象传递给此回调(如果您需要在回调中包含此对象的数据)。
发布于 2015-02-23 01:09:56
其他答案中提供的代码示例没有描述如何将回调重定向到每个对象的成员函数,其中可能包含任意数量的对象。让你的类成为单例会限制你的设计,并且不会扩展到多个glfw窗口。
可伸缩的解决方案是将glfw窗口用户指针设置为您的对象,然后在回调中获取它,并调用成员函数:
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);
}
此解决方案更短,适用于任何数量的窗口。
发布于 2016-12-12 02:46:51
我也有同样的问题,在阅读了这篇文章后,我想出了一个类似的解决方案。我觉得这样会更干净一点。它基于静态函数,但它嵌套在我们设置所有内容的类中。
Header如下所示:
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;
};
};
和源代码:
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);
}
https://stackoverflow.com/questions/7676971
复制相似问题