允许静态函数访问数据,而不将数据作为参数传递 我在我的C++应用程序中使用GLFW作为窗口,我尝试使用GLFW的回调来获取输入事件。例如,这是获取关键事件的方式: void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods){ // Do something with event data. } int main(){ // initialize window (I have no problems with this step) glfwSetKeyCallback(window, key_callback); // Now when a key is pressed in the window it will call this function. }
问题: 在我的允许静态函数访问数据,而不将数据作为参数传递 我在我的C++应用程序中使用GLFW作为窗口,我尝试使用GLFW的回调来获取输入事件。例如,这是获取关键事件的方式: void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods){ // Do something with event data. } int main(){ // initialize window (I have no problems with this step) glfwSetKeyCallback(window, key_callback); // Now when a key is pressed in the window it will call this function. },c++,callback,global-variables,static-methods,glfw,C++,Callback,Global Variables,Static Methods,Glfw,问题: 在我的key\u回调中,我想使用在key\u回调函数之外声明的变量,因为我无法更改key\u回调的参数,所以我无法传递对该变量的引用 现在,在上面给出的示例中,我可以简单地在int main()之外声明我的变量,key\u callback和int main()都可以访问该变量的同一实例 我想要的用途: 我想要一个WindowWrapper类来创建和管理glfwWindow的生命周期,这将包括设置事件回调 WindowWrapper.h // Includes class WindowW
key\u回调
中,我想使用在key\u回调
函数之外声明的变量,因为我无法更改key\u回调
的参数,所以我无法传递对该变量的引用
现在,在上面给出的示例中,我可以简单地在int main()
之外声明我的变量,key\u callback
和int main()
都可以访问该变量的同一实例
我想要的用途:
我想要一个WindowWrapper
类来创建和管理glfwWindow
的生命周期,这将包括设置事件回调
WindowWrapper.h
// Includes
class WindowWrapper{
private:
Centrum* g_centrum_;
GLFWwindow* window_;
std::thread thread_;
public:
WindowWrapper();
WindowWrapper(Centrum* g_centrum);
~WindowWrapper();
private:
// Callbacks
static void key_callback(
GLFWwindow* window, int key, int scancode, int action, int mods
);
};
WindowWrapper.cpp
WindowWrapper::WindowWrapper(Centrum* g_centrum){
g_centrum_ = g_centrum;
// Initialize window
glfwSetKeyCallback(window_, key_callback); // Problems
// Window loop and OpenGL stuff
}
WindowWrapper::~WindowWrapper(){
thread_.join(); // Don't worry about this, it works but, I will make it safer.
glfwDestroyWindow(window_);
printf("WindowWrapper Completely Destructed!\n"); // For testing purposes
}
void WindowWrapper::key_callback(
GLFWwindow* window, int key, int scancode, int action, int mods
){
// This function is declared static in the class declaration.
// And as a result I cannot use g_centrum_ since it is a non-static variable
// Essentially I want to be able to access g_centrum_ from this function
g_centrum_->input_eventmanager_->key_eventmanager_->
TriggerKeyEvent(key, action, mods);
}
我想到的第一种方法是传递对g_centrum
的引用,但是GLFW不会对回调的参数产生任何偏差
我的第二次尝试是在构造函数中声明和定义回调,但您不能这样做
我的第三次尝试是使
g\u centrum\uu
静态,但我必须在构造函数之外给它引用,我认为这不是一个优雅的解决方案。在注册回调之前,使用glfwSetWindowUserPointer()
将包装器指针与窗口相关联。调用回调时,可以使用glfwGetWindowUserPointer()
检索它。中介绍了这些API
窗口用户指针
每个窗口都有一个用户指针,可以使用glfwSetWindowUserPointer设置,并使用glfwSetWindowUserPointer获取。这可以用于您需要的任何目的,并且在窗口的整个生命周期内不会被GLFW修改
例如,您可以在WindowWrapper
构造函数中执行此操作:
WindowWrapper::WindowWrapper(Centrum* g_centrum){
g_centrum_ = g_centrum;
// Initialize window first
...
// Now, associate the wrapper to the window
glfwSetWindowUserPointer(window_, this);
glfwSetKeyCallback(window_, key_callback); // Problems
// Window loop and OpenGL stuff
}
然后,在回调中:
void WindowWrapper::key_callback(
GLFWwindow* window, int key, int scancode, int action, int mods
){
void *data = glfwGetWindowUserPointer(window);
WindowWrapper *w = static_cast<WindowWrapper *>(data);
w->g_centrum_->input_eventmanager_->key_eventmanager_->
TriggerKeyEvent(key, action, mods);
}
void WindowWrapper::key\u回调(
GLFWwindow*窗口,int键,int扫描码,int操作,int mods
){
void*data=glfwGetWindowUserPointer(窗口);
WindowWrapper*w=静态_转换(数据);
w->g\u centrum->input\u eventmanager->key\u eventmanager->
TriggerKeyEvent(按键、动作、mods);
}
您可以有一个静态映射,将每个GLFWindow*
映射到其相应的窗口包装器
:
private:
static std::map<GLFWindow*, WindowWrapper*> m_instanceMap;
...
在析构函数中,将其删除:
m_instanceMap.erase(window_);
现在,在(静态)回调方法中,您可以查找类实例,并调用每个实例方法:
void WindowWrapper::key_callback(
GLFWwindow* window, int key, int scancode, int action, int mods)
{
WindowWrapper* pThis = m_instanceMap[window];
pThis->keyHandler(key, scancode, action, mods);
}
其中,
keyHandler()
是一个常规实例方法。与其让WindowWrapper
持有GLFWwindow*
指针,不如从GLFWwindow
派生它。然后,key\u callback
可以将其window
参数向下转换为WindowWrapper*
并访问其成员。GLFW是一个框架,GLFWwindow
是不透明的。@jxh它是某种结构。你不需要知道它里面有什么才能从中得到。如果感觉不正确,另一种方法是定义一个结构,该结构将GLFWwindow
作为它的第一个成员(然后是额外的成员)。同样,您可以将GLFWwindow*
指针强制转换为该结构指针,并访问额外的成员。@IgorTandetnik:您不能从不透明对象继承。您所说的“不透明对象”是什么?我的C++标准的副本没有提到这样的事情。如果框架不提供支持关联用户数据(+ 1)的话,映射是唯一的方法。是的,在没有真正支持的前提下,这是一个通用的解决方案。因为在这个特定的案例中它显然是受支持的,所以使用它当然更好。我有点迷路了,API页面并没有给我太多的东西去继续(我对这一点了解甚少)。你能举个抽象的例子吗?
void WindowWrapper::key_callback(
GLFWwindow* window, int key, int scancode, int action, int mods)
{
WindowWrapper* pThis = m_instanceMap[window];
pThis->keyHandler(key, scancode, action, mods);
}