【发布时间】:2015-05-16 11:45:48
【问题描述】:
我有一个有一些内部状态的类。该类使用名为 GLFW 的 C 库来处理窗口管理和键盘输入。
这个类看起来像这样:
class Object {
public:
Object(...);
...
private:
int _member_variable; // Internal state
GLFWwindow *_window;
...
}
关于 GLFW 的背景
GLFW 是一个处理窗口处理和键盘输入的 C 库。它使用回调函数来报告用户在窗口获得焦点时按键的时间。
void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
printf("User pressed key #%d\n", key);
}
要将回调函数绑定到窗口,请使用名为 glfwSetKeyCallback 的函数。
// This will bind the `key_callback` function to `window`.
glfwSetKeyCallback(window, key_callback);
我遇到的问题
我想通过一个关键回调函数修改我的类的内部状态,而不依赖于static 存储的状态。我不能拥有全局状态,因为我希望能够创建多个 Object 实例并让它们彼此独立工作。
假设在这种情况下,我希望在用户每次按键时增加 _member_variable。
我想做这样的事情:
// Private method for dealing with key presses.
void Object::key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS)
++_member_variable; // Increment the internal state
}
Object::Object(GLFWwindow *window, ...)
: _window(window), ...
{
glfwSetKeyCallback(window, key_callback);
}
但这不起作用,因为Object::key_callback 是Object 的成员函数,并且需要不可见的this 参数。 (Object::*)(GLFWwindow *, int, int, int, int) 无法转换为 (*)(GLFWwindow *, int, int, int, int)。
我尝试过的
- 不能将私有成员函数传递给 GLFW API。考虑到成员函数需要不可见的
this参数,这是可以理解的。 - 我也尝试使用 lambda 来捕获我想要的状态,但这也没有用。
有没有一种方法可以在不依赖全局状态的情况下从传递给 C API 的函数修改类状态?就像在这种情况下,从传递给glfwSetKeyCallback的函数中增加_member_variable?
【问题讨论】:
-
问题恰恰出在
this参数上,而且c++ 修改了函数名以允许函数重载这一事实,所以我认为如果可能的话,传递一个c++ 类是非常困难的成员函数,就好像它是一个 c 回调一样。当然有一些选择,AFAIK 新的 c++ 标准使做这类事情变得更容易,但我不是专家。 -
只要 c-api 不提供传递用户数据的方法(如
this),这几乎是不可能的。您可以维护GLFWwindow*指针的静态映射作为键和指向相应类实例的指针。但这恐怕不容易维护。 -
@elias 如果你回答了这个问题,你会得到很多答案:当一个键被按下时,你将/如何找到成员函数的对象叫什么?
标签: c++ c class callback global-variables