質問

I'm currently working on a cross-platform 2D rendering engine using OpenGL and GLFW. I have a base window class called GameWindow, and a class called Game that inherits GameWindow. Game overrides a few virtual methods in the base class so that GameWindow can take care of frame-limiting, etc. In the constructor for GameWindow, I use glfwSetWindowSizeCallback to specify a method to be run when the window is resized. This method then calls the virtual on_resize method of GameWindow, which triggers the overriden method in Game. Calling any of the virtual methods from within GameWindow has the expected effect of calling the appropriate methods in Game. However, if the virtual methods are called from the window resize callback in GameWindow, the application crashes. I have worked around this by storing a static instance of GameWindow and calling the on_resize method of it from the callback. However, I'd rather not have to do this. Is there a better fix for this issue? Thanks in advance.

~ Michael K.

class GameWindow : Object {
    GLFWwindow* win;
    ...
    public GameWindow(...) {
        ...
        glfwSetWindowSizeCallback(win, (GLFWwindowsizefun)window_size_callback);
    }

    public void run(...) {
        ...
        on_render(renderElapsed);  // This works fine.
        ...
    }

    public virtual void on_resize(int width, int height) {}

    public void window_size_callback(GLFWwindow* window, int width, int height) {
        ...
        on_resize(width, height);  // This causes a crash.
    }
}

class Game : GameWindow {
    ...
    public override void on_render(double time) { ... }

    public override void on_resize(int width, int height) { ... }
}
役に立ちましたか?

解決 2

Just as a (very delayed) update, I started messing around with GLFW again and found that it actually has a way of handling this sort of thing: glfwSetUserPointer and glfwGetUserPointer. I ended up editing my code to store a pointer to the calling GameWindow instance. In the callback methods, I simply use glfwGetUserPointer to get said pointer, and cast it to the GameWindow type. I can then use the instance as I would normally.

EDIT: While apmasell's answer IS correct, it's mainly a solution for libraries that don't allow things like user pointers.

他のヒント

GLFWwindowsizefun does not take a target/context, so Vala has no way to pass the current GameWindow instance into the callback. This effectively means that this is null in the callback, so calling on_resize fails. Your cast is hiding the Vala compiler's error about it.

You should:

  1. Make window_size_callback a static method.
  2. Create some kind of lookup table to find GameWindow from GLFWwindow in a global variable. (You probably want GameWindow to be unowned in the lookup table and have the GameWindow destructor remove itself from the lookup table.
  3. In the callback, look up the right GameWindow and call the on_resize method on it.
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top