bvs
bvs

Reputation: 350

GLFW keycallback userpointer not carrying data

I'm trying to send data from my application to the GLFW keyCallback where I then access and modify that data. However, nothing I pass in can be accessed or changed without an app crash. What am I doing wrong?

//main.cpp
typedef struct
{
    string type, name;
} DebugUsrPtr;

//hot loop
{
    DebugUsrPtr myPtr;
    myPtr.type = "aaa";
    myPtr.name = "bbb";
    void *testPtr = &myPtr;

    glfwSetWindowUserPointer(myWin, testPtr);
    glfwSetKeyCallback(myWin, keyCallback0);
    glfwSetWindowUserPointer(myWin, myWin);
}

//input.cpp
void keyCallback0(GLFWwindow *window, int key, int scancode, int action, int mods)
{
    auto *myTest = static_cast<DebugUsrPtr*>(glfwGetWindowUserPointer(window));
    cout << "name test = " << myTest->name << endl; // ""
    myTest->name = "zzzz"; //prints "zzzz" for one frame then appcrash
}

Upvotes: 0

Views: 174

Answers (1)

Guillaume Racicot
Guillaume Racicot

Reputation: 41800

On this line:

glfwSetWindowUserPointer(myWin, myWin);

When you set that, the user pointer will now point to the window structure, not your struct. So when the callback is called (it is called later), it no longer points to your debug structure, but to the windows pointer.

You need to send the pointer to your structure and let it there as long as you think you will need it.

You have another error, the debug structure is destroyed before the callback is called:

{
    DebugUsrPtr myPtr;
    myPtr.type = "aaa";
    myPtr.name = "bbb";
    void *testPtr = &myPtr;

    glfwSetWindowUserPointer(myWin, testPtr);
    glfwSetKeyCallback(myWin, keyCallback0);
    glfwSetWindowUserPointer(myWin, myWin);
} // debug structure destroyed here!

So when the callback is called later, it the debugs structure will be freed, and that will lead to undefined behaviour!

For that, I think you should declare your struct in the parent scope of your event loop. Just like this:

DebugUsrPtr myPtr;
// ...
{
    glfwSetWindowUserPointer(myWin, &myPtr);
    glfwPollEvents(); // the callback will be called here if user press keys!
}

If you're really doing C++, declare your struct like this instead:

struct DebugUsrPtr {
    std::string type, name;
};

If you want a different type or a different pointer for each callback, hold them all in a bigger struct:

struct AllPointers {
    DebugUsrPtr dbg;
    MouseUsrPtr mouse;
    // more...
};

Upvotes: 1

Related Questions