# question about passing functions in glut

This topic is 4824 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Ok, I hope I'm not being an asshole by skipping over the FAQ and just posting my question, but I figure its pretty specific and just merits a quick answer. I am also pretty new to graphis programming so bear with me etc. etc. Now then. I am making a terrain map generator/display. In order to avoid having to declare a bunch of global variables and just keep overall neatness at a maximum I tried putting as much as I can in an general GLInterface class (that I wrote). So very basically my program looks like this. class myclass { ///stuff }; class GLInterface { myclass c1; //otherstuff void RenderScene() { //stuff } void setupinterface() { //change window size and other stuff glutDisplayFunc(GLInterface::RenderScene); } startLoop(){ glutMainLoop(); } }; int main() { GLInterface GLI; GLI.setupinterface(); GLI.startLoop(); } However the line glutDisplayFunc(RenderScene); will not complile. It will not compile if I do not scope it with GLInterface:: and it will not compile if I put it in the main glutDispalyFunc(GLI.RenderScene); Please tell me that there is some way short of making RenderScene a global function to get this to work! Thanks a lot. George

##### Share on other sites
The glut callbacks are suppose to be plain non-method, functions. Methods(class-functions) and plain functions do not have the same signature so therefore you can't pass a class method as a function pointer. Try it out without glut. You'll get the same errors.

##### Share on other sites
The only way to bypass your little problem is if the function inside the class were static. Since static methods have the same signature as non-class functions.

##### Share on other sites
Quote:
 Original post by KhaosifixThe glut callbacks are suppose to be plain non-method, functions. Methods(class-functions) and plain functions do not have the same signature so therefore you can't pass a class method as a function pointer. Try it out without glut. You'll get the same errors.

True and not true[smile].
It would work perfectly if the member functions are static. Since they aren't one can use std::mem_fn together with std::bind1st to achieve this (or boost.bind).

Regards,
Pat.

Oh, you already noticed - just ignore the first part [smile]
[/edit]

^ [cool]

##### Share on other sites
Since IMHO the STL is a bit clumsy on the bind1st and mem_fn part, I decided to just post an example:

class GLInterface {     myclass c1;     //otherstuff     void RenderScene() {       //stuff     }     void setupinterface() {      //change window size and other stuff      glutDisplayFunc(std::bind1st(std::mem_fun(&GLInterface::RenderScene), this));     }     void startLoop() {        glutMainLoop();     }};

Hope this helps,
Pat.

##### Share on other sites
thanks a lot, I'll try it right now and see what happens.
I'm afraid I don't know what it would mean to have a static method (I mean I know I could put the word static there but I don't know waht it would do) could someone explain that to me so I could see if that method would be applicable?

##### Share on other sites
darookie, what you recomended std::bind1st(std::mem_fun(&GLInterface::RenderScene), this)
didn't work problem with second argument type as best as I can decipher from the compiler error

##### Share on other sites
Hope this helps :

class CClass{   public :      static GLvoid RenderScene( ) ;    // declare it as static in the class} ;GLvoid CClass::RenderScene( ){ // Important step : define the function outside of the class. Can't be inside.  // Draw stuff.}void main( ){   // Function calls are a little odd. But this is how you call a static method.   CClass::RenderScene( ) ;   }

##### Share on other sites
Quote:
 Original post by Togakangaroothanks a lot, I'll try it right now and see what happens.I'm afraid I don't know what it would mean to have a static method (I mean I know I could put the word static there but I don't know waht it would do) could someone explain that to me so I could see if that method would be applicable?

You could use the PIMPL idiom to achieve that:
class ActualImplementation {private:   // declare datapublic:   // methods   void doSomething();};class PublicInterface {private:    static ActualImplementation *pimpl;public:    PublicInterface() {        if (0 == pimpl) {            pimpl = new ActualImplementation;        }    }    ~PublicInterface() {        delete pimpl;        pimpl = 0;    }    static void doSomething() {        // dispatch to actual implementation        assert (pimpl);        pimpl->doSomething();    }};

You can use PublicInterface::doSomething like a free function now and pass it as a callback to GLUT for example.

Regards,
Pat.

##### Share on other sites
Another idea to bypass the static-problem:

class GLInterface {     myclass c1;     static GLInterface * instance;     //otherstuff     void RenderScene() {       //stuff     }     static void InternalRender() {         assert(instance);         instance->RenderScene();     }public:     GLInterface() {            instance = this;     }     void setupinterface() {      //change window size and other stuff      glutDisplayFunc(InternalRender);     }     void startLoop() {        glutMainLoop();     }};

A little less confusing, I hope [smile]

##### Share on other sites
damn, that's clever darookie,I tried using the second one. Still something's up though. It compiles but then complains while linking
TerrainGen error LNK2020: unresolved token (0A000027) ?instance@GLInterface@@1PAV1@A

any ideas?

##### Share on other sites
Quote:
 Original post by Togakangaroodarookie, what you recomended std::bind1st(std::mem_fun(&GLInterface::RenderScene), this)didn't work problem with second argument type as best as I can decipher from the compiler error

Mea culpa! This is not possible because of the different calling conventions...
All GLUT callback types are declared as 'extern "C"' meaning __cdecl has to be used, which is not possible for __thiscall types (all non-static member functions are silently declared this way). I don#t know of any way to trick mem_fun into using a __cdecl member function, though.

Maybe the other two solutions are for you?

Good luck,
Pat.

##### Share on other sites
Quote:
 Original post by Togakangaroodamn, that's clever darookie,I tried using the second one. Still something's up though. It compiles but then complains while linkingTerrainGen error LNK2020: unresolved token (0A000027) ?instance@GLInterface@@1PAV1@Aany ideas?

Yeah.
// add this line somewhereGLInterface * GLInterface::instance = 0;

You need to define static member variables somewhere. They are rarely used so I understand you didn't know that.

Regards,
Pat.

##### Share on other sites
Why use GLUT in the first place?

##### Share on other sites
Quote:
 Original post by KhaosifixWhy use GLUT in the first place?

Now that's not very helpful comment[wink]
The same issue occurs with every C library that takes callbacks as parameter. So this isn't a problem specific to GLUT.
<irony>
Blame C++ for that whole name-mangling insanity and messed up interop system.
</irony>

In the end this we all learned a valuable lesson again: C++ is hard and has its caveats [smile].

Best regards,
Pat.

##### Share on other sites
Is that right? GLInterface * GLInterface::instance = NULL;

did you mean GLInterface::instance I = NULL;

either way, I tried both, maybe I'm not putting them in the right place.

Oh well, I suppose I could make all the functions global. Its just a pain in the ass. Thanks anyways guys.

##### Share on other sites
Oh shit, that did it! Thanks man, I'm an idiot for doubting you. Looks like someone's going to get credits in an about box...

##### Share on other sites
class GLInterface {     myclass c1;     static GLInterface * instance;     //otherstuff     void RenderScene() {       //stuff     }     static void InternalRender() {         assert(instance);         instance->RenderScene();     }public:     GLInterface() {            instance = this;     }     void setupinterface() {      //change window size and other stuff      glutDisplayFunc(InternalRender);     }     void startLoop() {        glutMainLoop();     }};static GLInterface * GLInterface::instance = NULL;