0

I want to take the OpenGL functionality from the main source file to a separate class.

// Initialize rendering (GLUT and GLEW)
gfxMgr.init(argc, argv);
...
glutReshapeFunc(gfxMgr.resizeWindow);
glutKeyboardFunc(gfxMgr.keyPressed);
glutKeyboardUpFunc(gfxMgr.keyReleased);

The problem started with defining the callback functions within the class' implementation file. I declared them in the header file as static.

static void init(int , char** );
...
static void drawScene();
static void whenIdle();

Then another problem followed. I want to use a non-static boolean fullScreen variable (as declared in the header) in one of the static functions of my implementation file, but the IDE tells me that "a non-static member reference must be relative to a specific object".

void GfxMgr::init(int argc, char** argv)
{
    ...
    if(fullScr) glutFullScreen();
    ...
}

I don't understand the problem and I don't know what to do. I declared the boolean and a few other variables as static but came up with a bunch of unresolved external symbol errors.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Andrei
  • 135
  • 5
  • 18

1 Answers1

1

I don't understand the problem

You need to understand what static member functions are. See this tutorial for example. I also recommend the previous one about static member variables.

In short, static member functions don't know anything about instances of the class. Non-static member variables are bound to an instance of the class. Therefore non-static member variables are unavailable to static member functions.

and I don't know what to do.

What you should do depends on what your class and it's functions are supposed to do.

  • If the behaviour of the function is supposed to depend on value of a member variable of an instance, then the function must be non-static and you must call it on the instance.
  • If the function is supposed to only depend on global state of the class rather than an instance, then the variables the function accesses must be part of that global state (static members).

C callbacks cannot be member functions. Therefore they cannot depend on state of an instance (except a global instance, see this tutorial)

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • OK. I've changed some of the functions back to non-static but got this instead: `error C3867: 'GfxMgr::drawScene': function call missing argument list; use '&GfxMgr::drawScene' to create a pointer to member`. Since it's callback, it's not supposed to have any arguments, and I've been fiddling enough with pointers on this issue. – Andrei May 05 '14 at 09:59
  • @Andrey: Now you have the problem, that C++ class member functions can not be used as callbacks for C style callbacks. You need to create some association between the GLUT window and a class instance. – datenwolf May 05 '14 at 10:02
  • @datenwolf : Actually, a few minutes after I've posted this thread, I've noticed an article on the right side of the page that suggested I use "thunk" or "trampoline" (see here: http://stackoverflow.com/questions/2420346/c-api-function-callbacks-into-c-member-function-code/2420382#2420382 ), though I do not understand those concepts at all; they are not well explained. – Andrei May 05 '14 at 10:07
  • 1
    @Andrey, See the second tutorial in my answer, the first example of 3.5 is thunking. However, if gl callback registering doesn't allow passing arbitrary pointer to the callback function, you can't use that option. In that case you must either use a static member or a helper function which uses a global instance. – eerorika May 05 '14 at 10:15
  • @user2079303 : I will try that. Otherwise, I did use static members and it didn't work out. As for the idea of a helper function, then I'm not sure what it could possibly do with the gfxMgr. – Andrei May 05 '14 at 10:22
  • @datenwolf : So, those were all C-style callbacks? That's the only way (as you see in the code) in which I saw them treated. What would I have to do to make them C++-style callbacks? – Andrei May 05 '14 at 16:31
  • 1
    @Andrey: You need some mapping, from GLUT windows `int glutGetWindow(void)` to the `GfxMgr` class instance associated with that window. I suggest using a static class member of type `std::map` and in `GfxMgr::init` after `glutCreateWindow` has been called and before registering the callbacks adding a new mapping from the GLUT window to the class instance `window_map[glutGetWindow()] = this;`. Then in the static callback functions wrap the static trampolines to class instance methods `static void GfxMgr::s_display(){window_map[glutGetWindow()]->display();}` – datenwolf May 05 '14 at 16:45
  • @user2079303 : OK, I'm looking at http://www.newty.de/fpt/callback.html#member . I really don't understand how the glut functions would fit into this picture. I'm passing an argument-less function to a callback function in `int main()`. Where in your example can I do the same? – Andrei May 05 '14 at 20:57
  • 1
    @Andrey, you'd have to do it like in example B. It has a static member function `TClassB::Wrapper_To_Call_Display(char* string)` as the callback. To have a callback with no parameters, just leave the parameter out. The static member calls a non-static member function on a global instance. – eerorika May 05 '14 at 22:17