0

I am trying to pass a function to GLUT call back glutSpecialFunc.

It's working perfectly when I try to pass a static function(specialKeyProcessor) to it.

When I moved this function to a class(KeyBoardMovement) specialized in processing keyboard-related functions it does not seem to work:

.... KeyboardMovement keyboard; .... glutSpecialFunc(keyboard.specialKeyProcessor);

The error pops out: Reference to non-static member function must be called.

I dont understand this error because I cant see any difference between the same function placed in different places.

Roy Li
  • 315
  • 1
  • 4
  • 7

2 Answers2

2

The glutSpecialFunc function sets a per-window callback. If you are using OpenGLUT, it also allows you to associate some data with each window using glutSetWindowData.

Therefore, you can make a global shim function like this:

void specialKeyProcessor(int key, int x, int y) {
    KeyboardMovement *keyboard = static_cast<KeyboardMovement *>(glutGetWindowData());
    keyboard->specialKeyProcessor(key, x, y);
}

and associate your keyboard handler using glutGetWindowData:

glutSetWindowData(static_cast<void *>(&keyboard));

If you need to store more than one piece of window data, you can store a pointer to a window-specific struct with fields for each window-specific data.


If you aren't using OpenGLUT, you can consider making a std::map mapping window IDs to your global data. Then you can take a similar approach to the above to have window-specific data.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • 1
    I'm not seeing any mention of `glutSetWindowData()` in the [spec](http://www.opengl.org/resources/libraries/glut/glut-3.spec.pdf). Are you sure that's not a FreeGLUT or OpenGLUT extension? – genpfault Feb 14 '13 at 01:47
  • 1
    Darn, it is an OpenGLUT extension. The manual page didn't make it clear. The documentation does say that a viable alternative is to maintain your own mapping from window IDs to member data, which would be easy to do with a `std::map`. – nneonneo Feb 14 '13 at 02:31
0

C++ doesn't support closures, which means it can not turn a class instance, together with a method into a function pointer that when called will execute the method of the class instance.

Unfortunately GLUT doesn't support data aware callbacks, like most other C callbacks API do. So it's either write a wrapper function, that will call on a global instance of your class, or well, employ some really dirty tricks using a library called "ffcall" that can practically create new functions at runtime, which can be parametized and act as a closure you can pass to GLUT. But that's really dark stuff and the right thing would be to ditch GLUT.

datenwolf
  • 159,371
  • 13
  • 185
  • 298