gpt4 book ai didi

c++ - 有没有办法从传递给 C API 的函数指针修改类状态?

转载 作者:搜寻专家 更新时间:2023-10-31 00:32:51 26 4
gpt4 key购买 nike

我有一个具有一些内部状态的类。该类使用称为 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);
}

要将回调函数绑定(bind)到窗口,您可以使用名为 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_callbackObject 的成员函数并且需要不可见的 this 参数。 (Object::*)(GLFWwindow *, int, int, int, int)不能转换为(*)(GLFWwindow *, int, int, int, int).

我尝试过的

  • 不可能将私有(private)成员函数传递给 GLFW API。考虑到成员函数需要不可见的 this 参数,这是可以理解的。
  • 我也曾尝试使用 lambda 来捕获我想要的状态,但这也没有用。

有没有一种方法可以在不依赖全局状态的情况下从传递给 C API 的函数修改类状态?就像在这种情况下从传递给 glfwSetKeyCallback 的函数中递增 _member_variable 一样?

最佳答案

是的,这是可能的。该解决方案是 GLFW 的 API 支持的解决方案。

典型的 C 库允许您在注册回调时将不透明的指针传递给用户数据。 glfwSetKeyCallback 没有。

相反,在 GLFW 中,您调用 glfwSetWindowUserPointer 以在 GLFWWindow 中设置一个用户指针字段。在您的 Object 构造函数中或在实际创建窗口的任何位置将其设置为 this。然后,将静态成员函数添加到您的 Object 类。这个函数可以是私有(private)的。将其作为回调传递给 glfwSetKeyCallback。调用此回调时,使用 glfwGetWindowUserPointerGLFWWindow 检索用户指针,将其转换为 Object*,并使用它来分派(dispatch)调用到该对象的非静态成员函数或直接修改数据成员。

http://www.glfw.org/docs/latest/window.html#window_userptr

编辑

为了使这个答案更加完整,让我评论一下您尝试解决此问题的方法。

  • It is not possible to pass a private member function the GLFW API. That is understandable considering that the member functions require the invisible this argument.
  • I have also tried using a lambda to capture the state I want but that also did not work.

确实可以像我和@derhass 描述的那样(几乎同时)传递一个私有(private)的static 成员函数。但是,我确定您的意思是非静态成员函数。如您所见,您需要 this 指针来分派(dispatch)到正确的对象。看起来您可以使用 glfwSetWindowUserPointer 设置 this 指针,然后传递 pointer to a private non-static member function .但是,这行不通。指向成员函数的指针通常被实现为除了地址之外还带有额外数据的“胖”指针。例如,请参阅此 discussion .如果您设法将一个转换为普通指针并将其传递给 C 库,您将以某种方式被截断。即使您可以避免强制转换截断(我认为您做不到),C 库也没有足够的存储空间来存放胖指针,因此无法将其原封不动地返回给您。

同样,lambda 通常也是如此。

关于c++ - 有没有办法从传递给 C API 的函数指针修改类状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30275250/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com