Passing class member functions to GLUT

Started by
4 comments, last by rip-off 6 years, 3 months ago
So here's what I'm doing:
class CFGapp
{

...

public:
	void RenderScene(void);    // Draws everything on the screen

...

};
Then in the class constructor I do this:
glutDisplayFunc(RenderScene);        // Our display function...
And the compiler (VS.NET) gives me this: CFreeGLUTapp.cpp(30): error C2664: 'glutDisplayFunc' : cannot convert parameter 1 from 'void (void)' to 'void (__cdecl *)(void)' Any ideas how to fix this guys?
Advertisement

  • GLUT is a C API. It cannot accept C++ constructs as parameter.

  • Pointers to non-static member functions can never be used where a pointer to non-member function is expected. The two are very different beasts. See this article for an in-depth exploration.



That being said, the proper syntax for manipulating pointers to members is as follow:

class CFGapp{public:   void RenderScene(void);    // Draws everything on the screen};void (CFGapp::* pmf)(void); // pointer to member functionpmf = &CFGapp::RenderScene; // Assign the function to the pointerCFGapp App;                 // The object we're going to call the function on.CFGapp *pApp = &App;        // To show the two forms.(App.*pmf)();               // Call via object(pApp->*pmf)();             // Call via object pointer


Notice that we had to provide the object the member function is supposed to work with. Even what you had tried had be legal, the display function callback would have had no way of figuring what to use for the this pointer. (Again, see the article mentioned above for a possible solution - though not for GLUT, unfortunately - C APIs and all that).
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
You can't pass a member function to GLut because a member function can only be called from an instance of the class and GLut doesn't have an instance of your class to call it on. It doesn't even know that your class exists. You can either use a static member function and have that static member call the RenderScene function of a current instance or have a non-member function that does the same thing, i.e.:
class CFGapp{	public:		void RenderScene();		static void Render(){application.RenderScene();}	private:		static CFGapp application;};glutDisplayFunc(GFGapp::Render);

or
class CFGapp{	public:		void RenderScene();};CFGapp application;void Render(){	application.RenderScene();}glutDisplayFunc(Render);


Enigma

Thanks Enigma , i found this topic from google. Your first example does not works, cannot use the object context with dynamic vars, but the second example works fine. My solution is call the init functions of glut from main file without class and call the class for drawing from static function:


#include <time.h>
#include "core/Log.h"
#include "core/Core.h"

Log     log;
Core    core; // <- The solution (Declare out of main function
              //    and call the consructor, make the context)
clock_t last_clock;
float   fps = 60.0; // Limit to 60 FPS

void draw()
{
    core.draw(); // <- The solution (call object function)

    // Limit FPS
    while((((float)clock() - (float)last_clock) / (float)CLOCKS_PER_SEC) < (1.0 / fps)){}
    last_clock = clock();
    
    glutPostRedisplay();
}

int main(int argc, char **argv)
{
    core.init();
    last_clock = clock();

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);
    glutInitWindowSize(800, 800);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("GLEngine");
    glutDisplayFunc(draw); // <- The solution (call static function)
    glutMainLoop();

    return 0;
}

In the Core object call the physical objects:


void Core::draw()
{
    glClearColor(0.4, 0.4, 0.4, 1.0); // Background
    glClear(GL_COLOR_BUFFER_BIT);

    // Draw objects here ...

    glFlush(); // Finish of drawing
}

 

Please do not reply to old topics, thanks.

This topic is closed to new replies.

Advertisement