c++ - 在不将数据作为参数传递的情况下授予静态函数访问数据的权限

标签 c++ callback global-variables static-methods glfw

我正在为我的 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.
}

问题:

在我的 key_callback我想使用在 key_callback 之外声明的变量功能,因为我不能改变 key_callback 的参数我无法传递对变量的引用。

现在,在上面给出的示例中,我可以简单地在 int main() 之外声明我的变量和两个key_callbackint 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_centrum_静态的,但我必须在构造函数之外给它引用,我认为这不是一个优雅的解决方案。

最佳答案

在注册回调之前,使用 glfwSetWindowUserPointer() 将包装器指针关联到窗口。当您的回调被调用时,您可以使用 glfwGetWindowUserPointer() 来检索它。 GLFW documentation 中描述了这些 API .

Window user pointer

Each window has a user pointer that can be set with glfwSetWindowUserPointer and fetched with glfwGetWindowUserPointer. This can be used for any purpose you need and will not modified by GLFW throughout the life-time of the window.

例如,您可以在 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);
}

关于c++ - 在不将数据作为参数传递的情况下授予静态函数访问数据的权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27596861/

相关文章:

c++ - 如何检查boost线程正在运行并杀死它

c++ - 您如何在 C 预处理器中使用定义进行逻辑异或

c++ - 取代 std::tie 滥用的结构化绑定(bind)

c++ - 获取有关重新定义的错误(OpenGL 4.0 Shading Language Cookbook)

javascript - 正确使用 Web Font Loader 事件/非事件回调

swift - 使用默认参数值声明协议(protocol)函数

javascript - 从回调中突破 "super function"

ios - 将标签变成全局变量

excel - 如何在 Excel VBA 中声明全局变量以在整个工作簿中可见

c - 如何在函数体内引用与局部变量同名的全局变量?