views:

295

answers:

4

I know this thing works:

void myDisplay()
{
...
}
int main()
{
...
glutDisplayFunc(myDisplay)
...
}

so I tried to include myDisplay() function to a class that I made. Because I want to overload it in the future with a different class. However, the compiler complains that

argument of type 'void (ClassBlah::)()' does not match 'void(*)()' .

Here is the what I try to make:

class ClassBlah
{
   ....
   void myDisplay()
   ....
}
......
int main()
{

    ...
    ClassBlah blah
    glutDisplayFunc(blah.myDisplay)
    ...
}

Does anybody knows how to fix this problem? Many thanks.

+5  A: 

Firstly, there is an implicit "this" pointer in non-static member functions, so you'll need to change your void myDisplay() in ClassBlah to be static. It's awkward to work around this limitation, which is why the C++ faq lite says don't do it

Then, you should be able to pass the functions as ClassBlah::myDisplay.

Depending on your motivation for overloading (ie are you going to hotswap implementations in and out at runtime, or only at compile time?) you might consider a utility "handler" static class that contains a pointer to your base class, and delegates responsibility through that.

kibibu
A: 

You can use Boost bind for member functions, for example creating a thread on a member function:

class classA
{
public:
    void memberThreadFunc(int i);
};

void main()
{
    classA a;
    boost::thread( boost::bind(&classA::memberFunc, &a, 123) );
}
Inverse
kibibu
I doubt boost::bind will work here, as that surely returns a structure that has a () operator, something that glutDisplayFunc can't use.
Thanatos
Bind can't help here. The function being called requires a callback of `void(*)()` type. A 0-ary function object can't be used.
Joe Gauterin
A: 

You can't. glutDisplayFunc takes a parameter of type void(*)(), not void (ClassBlah::)(). Unless you're willing and able to alter the source of glut, you're out of luck.


Many C APIs that use callbacks pass a user-specified void* parameter to the callback, which you can use to store a pointer to your class. You can then pass a free function which casts the user data to a class pointer and then calls the member function. However, the way glut is designed doesn't allow that.

Joe Gauterin
+1  A: 

I ran into this problem writing a C++ Glut engine myself. Here's how I worked around it:

I placed these at the top of my program.cpp / main.cpp

// Function prototypes
void doRendering( void );
void processMouse( int, int ) ;
void processMouseClick(int button, int state, int x, int y);
void keyboardInput(unsigned char c, int x, int y);

Assign these functions to glut's callbacks here:

glutDisplayFunc(doRendering);
glutIdleFunc(doRendering);
glutPassiveMotionFunc(processMouse);
glutMotionFunc(processMouse);
glutMouseFunc(processMouseClick);
glutKeyboardFunc(keyboardInput);

Create my own class which handles these on its own and then make the contents of our static functions simply call methods on the instance of this class. Your main function should create a new instance of the class in main (in my case... App *newApp).

void doRendering( void )
{
    newApp->updateScene();
    newApp->drawScene();
}

void processMouse(int x, int y)
{
    newApp->processMouse(x, y);
}

void processMouseClick(int button, int state, int x, int y)
{
    newApp->processMouseClick(button, state, x, y);
}

void keyboardInput(unsigned char c, int x, int y)
{
    newApp->keyboardInput(c, x, y);
}

Hope that explains it.

Corwin