开发者

How to pass a class method as a GLUT callback?

开发者 https://www.devze.com 2022-12-23 15:40 出处:网络
I know this thing works: void myDisplay() { ... } int main() { ... glutDisplayFunc(myDisplay) ... } so I tried to include myDisplay() function to a clas开发者_高级运维s that I made. Because I want to

I know this thing works:

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

so I tried to include myDisplay() function to a clas开发者_高级运维s 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?


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.


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.


My way to solve this is simple:
First make a pointer before main function.
At the beginning of the the main function set pointer to instance of your class.
Then in new defined function for rendering, You can acces your object with global pointer.

/**
       Class argon is defined in external header file.
*/

Argon *argonPtr;

void renderScene();

int main()
{      
   Argon argon;
   argonPtr = &argon;

   glutDisplayFunc( render );  
}

void render()
{
   RenderStuff();
   argonPtr->Render();  
}

Hope it works for You, for me it does.


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) );
}


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消