Search code examples
javagame-enginelwjgl

How can I use glfwSetWindowUserPointer in LWJGL 3?


I'm trying to make a Window class to abstract all the GLFW stuff. The thing is that I don't know how to use glfwSetWindowUserPointer in LWJGL.

I've used the function before, but in C++. Now I'm moving to Java, using LWJGL.

In C++, I would do something like:

    glfwSetWindowUserPointer(myWindow, &myData)

But in LWJGL the function takes 2 long, where the first argument is the window handle, but I don't know what to do with the second one.

How can I pass a pointer to my object containing all the data I need inside the callbacks?

Thanks in advance


Solution

  • To expand on @elect's comment about JNINativeInterface and memGlobalRefToObject:

    import org.lwjgl.system.MemoryUtil;
    import org.lwjgl.system.jni.JNINativeInterface;
    
    class JavaObject {
        String message;
    
        JavaObject(String message) {
            this.message = message
        }
    }
    
    final long pointer = JNINativeInterface.NewGlobalRef(new JavaObject("Hello"));
    JavaObject object = MemoryUtil.memGlobalRefToObject(pointer);
    JNINativeInterface.DeleteGlobalRef(pointer);
    
    System.out.println(object.message) // => "Hello"
    
    // Already deleted the strong reference held by the native part of the application.
    object = MemoryUtil.memGlobalRefToObject(pointer);
    System.out.println(object) // => null
    

    On a bit of advice: I'd only use the GLFW user pointer for the callbacks set with glfwSetMonitorCallback and glfwSetErrorCallback. You don't need it for the window callbacks, as you set one callback per window, so you already have a reference to each Java wrapper class.

    class Window {
        final long handle;
    
        int width;
        int height;
    
        WindowObserver observer;
    
        Window(final long handle, final int width, final int height) {
            this.handle = handle;
            this.width = width;
            this.height = height;
    
            glfwSetWindowSizeCallback(handle, (handle, w, h) -> {
                if (observer != null) {
                    observer.windowDidResize(this, this.width, this.height, w, h);
                }
    
                this.width = w;
                this.height = h;
            });
        }
    }