GLFW调用静态key_callback

时间:2015-07-23 07:48:47

标签: c++ opengl input glfw static-functions

我环顾四周并阅读了很多关于静态函数和变量的知识,我已经明白,不能简单地在静态函数中调用非静态变量/函数等等,所以我的问题是如何解决这个问题问题我正在使用GLFW key_callback。

在GLFW,我们有这个:

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
  if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
    glfwSetWindowShouldClose(window, GL_TRUE);
}

我们像其他窗口相关的调用一样添加它:

glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, window_key_callback);

但是现在我希望能够在key_callback中按下'space'键时调用另一个类函数,如下所示:

在.h文件中我有

#include "A.h"

...

private: 
        A *anotherClass;

和我在构造函数中的.cpp文件

anotherClass = new A();

和其他

 static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
  if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
    antoherClass->draw();
}

而另一个类不是静态的,我只想在按下空格时开始绘图。

有人可以帮我这个吗?

3 个答案:

答案 0 :(得分:2)

你需要让antherClass成为一个全局变量,除此之外别无他法。通常一个回调函数应该采用用户提供的数据指针来允许传入外部信息,这里似乎存在API缺陷。

修改:结果证明您可以使用glfwSetWindowUserPointerglfwGetWindowUserPointer来执行此操作。

答案 1 :(得分:0)

正如yngum所指出的,您可以使用glfwSetWindowUserPointerglfwGetWindowUserPointer来访问您选择的void *指针。

这是一个像我这样传播的简单例子:

int main(void)
{
    t_MyDatas     datas;
    GLFWwindow    *window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
    //[...]
    glfwSetWindowUserPointer(window, (void *)&datas);
    glfwSetKeyCallback(window, &KeyCallback);
}

void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    t_MyDatas *datas;
    datas = (t_MyDatas *)glfwGetWindowUserPointer(window);
    //[...]
}

要记住的重要一点是从(void *)转换,然后转换回原始结构。

答案 2 :(得分:0)

我将与您的(非静态)keyCallback方法交互性创建一个类,然后创建您的应用程序类的实例,并在另一个静态的,keycallback函数内部的应用程序实例上调用keycallback方法,然后传递给glfwSetKeyCallback。这是我在开始使用此模板的新项目时经常使用的模板:

#include <iostream>
#include <string>
#include <GLFW/glfw3.h>

// obviously create headers with declarations seperate from definitions
// when spanning across multiple files, but for sake of brevity they
// have not been used.

// application.cpp
class Application {
public:
    GLFWwindow *window;

    Application(std::string title) {

      // boilerplate stuff (ie. basic window setup, initialize OpenGL) occurs in abstract class
      glfwInit();
      window = glfwCreateWindow(640, 480, title.c_str(), NULL, NULL);
      glfwMakeContextCurrent(window);

    }
    void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
      // basic window handling
      if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
      {
        std::cout << "exiting..." << std::endl;
        glfwSetWindowShouldClose(window, GL_TRUE);
      }
    }
    // must be overridden in derived class
    virtual void update() = 0;

    void gameLoop() {
      while (!glfwWindowShouldClose(window)) {
        //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // update function gets called here
        update();

        glfwPollEvents();
        glfwSwapBuffers(window);
      }
      glfwTerminate();
    }
};

// myapp.cpp
class MyApp : public Application {
public:
    MyApp(std::string title) : Application(title) {
      // my application specific state gets initialized here
    }
    void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
        Application::keyCallback(window, key, scancode, action, mods);
        if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) {
            // anotherClass.Draw();
            std::cout << "space pressed!" << std::endl;
        }
    }

    void update() override {
      // player.Update();
      // anotherClass.Draw();
    }
};

 Application* getApplication() {
     return new MyApp("MyApp");
 }

// main.cpp
// extern Application* getApplication();
Application *app;

static void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) {
    MyApp* myApp = (MyApp*)app;
    myApp->keyCallback(window, key, scancode, action, mods);
}

int main() {
    app = getApplication();
    glfwSetKeyCallback(app->window, keyCallback);
    app->gameLoop();
}