Passing Parameters To Callbacks?

Hi Floks:

Developing on Windows 10, Visual Studio 2015, C++.

I’m a few weeks into my OpenGL experience, a couple of decades into C++.

I have an aversion to globally passed arguments.

Apologies for the length of my first question. When I posted this in the OpenGL forum respondents asked what I wanted to do, what language I was using, and one directed me to this forum. So here is too much information.

Something I’d like to see in any callback function’s argument list is a parameter, a void pointer sized (32 or 64 bit) value.

An example would be the parameter you can pass to a Windows dialog procedure.

This is what I’m trying to do

I’m working my way through an exceptional series of OpenGL tutorials at learnopengl.com.

The author’s done a nice job of encapsulating camera functions into a camera class here, which I’ve been augmenting as I go through the lessons. I hope I can build this into a tool that serves me as I develop my own OpenGL applications.

I’d like to similarly encapsulate all of the keyboard, mouse, scroll wheel and other device interfaces found in this code example, from the definition of key_callback() down, into a class I can conveniently add to other projects.

I believe the obstacle that prevents me from wrapping these functions into a nice class is the lack of a parameter argument for functions like glfwSetKeyCallback() and callback functions conforming to GLFWkeyfun.

Pointers to class functions aren’t allowed. But if callback functions could have a parameter pointing to the instance of a class then, I believe, a call to that class callback function could work like this:

typedef class CAMERA_WRAPPER_BASIC
{
public:

    void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
    {
        Usefull stuff, with access to class variables
    }
}*CAMERA_WRAPPER_BASIC_PTR;
 
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode, 
                                                                  void *parameter)
{
    CAMERA_WRAPPER_BASIC_PTR(parameter)->key_callback(window, key, scancode, action, 
                                                                              mode);
}

So the callback will be a very simple non class function that uses it’s parameter as a pointer to the instance of the class, and calls the desired class function that has access to all of the class variables.

glfwSetKeyCallback() has no problem referring to key_callback() because it’s not a class function.

So, anyway…

Does any of this make sense? Is this something anybody should want to do?

Parameters aren’t available for callbacks, directly.

Is there a way to rig this, to make GLFW do something GLFW doesn’t want to do?

Again, I’d like to avoid passing global variables.

And again, sorry for the length of my first post.

Thanks
Larry

1 Like

You can associate one pointer to each GLFW window. You can easily put pointer to your object in there, and later retrieve it back in callback. See glfwSetWindowUserPointer for documentation.

You would use it like this:

class MyWindow
{
public:
	MyWindow()
	{
	    mWindow = glfwCreateWindow(...parameters...);
	    glfwSetWindowUserPointer(mWindow, this);
	    glfwSetKeyCallback(mWindow, onKey);
	}

	~MyWindow()
	{
	    glfwDestroyWindow(mWindow);
	}

    // virtual in case you want to override it in child class
    virtual void onKey(int key, int scancode, int actions, int mods)
    {
        // ... do whatever you want here
    }

private:
    GLFWwindow* mWindow;

    static void onKey(GLFWwindow* window, int key, int scancode, int actions, int mods)
    {
        MyWindow* obj = glfwGetWindowUserPointer(window);
        obj->onKey(key, scancode, actions, mods);
    }
};

Thanks mmozeiko:

That reply came less than 10 minutes after I’d finished editing my question.

It took me about 15 minutes to modify and test my code. Now I have the beginning of a tool that I think I’ll be able to use for a long time.

I looked for something like this in the description of GLFW windows, but I didn’t see it. I was probably looking for the word “parameter”.

I’d still think it would be good to be able to pass parameters to callbacks, but this is great.

Thanks again for showing it to me mmozeiko.

  Larry

The GLFW callbacks you’re referring to are global callbacks, i.e. for a given type of callback there can be only one function set for it. Thus it doesn’t add anything to have a user defined parameter set as part of the callback, since this can be done in user code as there’s no need to differentiate where the callbacks came from.

GLFW does pass you the window pointer, which you can the use to pass along with any of your own internal state to pass this on to the correct function or an object’s method.

1 Like

All I just read this and thank you. I am a very new programmer so this will take me awhile to understand but it is definitely on point!