0

我环顾四周,阅读了很多关于静态函数和变量的信息,我明白不能简单地在静态函数中调用非静态变量/函数等等,所以我的问题是如何解决这个问题我m 使用 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 中按下“空格”键时调用另一个类函数,如下所示:

在 .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();
}

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

有人可以帮我弄这个吗?

4

3 回答 3

2

您需要创建antherClass一个全局变量,没有其他方法可以解决这个问题。通常回调函数应该采用用户提供的数据指针来允许传入外部信息,这里似乎存在 API 缺陷。

编辑:原来你可以使用glfwSetWindowUserPointerglfwGetWindowUserPointer来做到这一点。

于 2015-07-23T16:55:18.320 回答
1

正如 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 *) 转换,然后转换回原始结构。

于 2017-06-29T16:58:45.877 回答
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();
}
于 2020-07-02T08:33:32.510 回答