From: <jc...@tu...> - 2004-04-23 09:08:13
|
I want to register the callback that is a method of a class, for example: [code] class MyClass() { public: MyClass( int *argc, char **argv ) { ...Init Code... glutDisplayFunc( display ); ...More Init Code... } void display() { ...My Display code... } } [/code] When I try this I get the following error; Cannot convert (MyClass::*)() to (*)(). Is it possible to achieve what I want to do or should I stick with a global display function. Thanks. ~~~~~~~~~~~~~~~~~~~~~~~ JC Oosthuizen ~~~~~~~~~~~~~~~~~~~~~~~ |
From: Richard R. <sf...@ol...> - 2004-04-23 09:51:34
|
On Fri, Apr 23, 2004 at 10:31:12AM +0000, jc...@tu... wrote: > I want to register the callback that is a method of a class, for example: >=20 > [code] > class MyClass() { > public: > MyClass( int *argc, char **argv ) { [...] > When I try this I get the following error; Cannot convert (MyClass::*)() > to (*)(). >=20 > Is it possible to achieve what I want to do or should I stick with a > global display function. You could use a static member function. In practice that is probably sufficient. In theory, the folks on comp.lang.c++ (I believe; I posted a URL before) apparently discussed this sort of issue before and concluded that Bjarne Stroustrup's _ARM_ was explicit that this was not legal the way that you want to do it (even with a static member function). My _ARM_ is too old to include the citation, so I haven't kept the reference handy. I can dig up the citation again if you like, but if you search for "Stroustrup" and "comp.lang.c++" in the freeglut-developer archives, you will probably find the old thread when we visited the topic a few months back. The short of it is that they recommend doing something like this (this is all from memory & recostruction): /*** In your header for {my_class} ***/ class my_class { public: static void cb_motion_func (int x, int y); void register_motion (void); }; /*** In your implementation file for {my_class} ***/ extern "C" { void window_motion (int x, int y) { window::cb_motion_func (x, y); } } /*** STILL in your implementation for {my_class} ***/ void my_class::register_motion (void) { glutMotionFunc (window_motion); } =2E..so the class member function, my_class::register_motion(), registers the callback. But it registers a legitimate C function. The C function, however, has access to the C++ class structure, so it calls a class member function with the data from GLUT. The my_class::cb_motion_func() should be static, since the C function has no way of knowing which instance to use. Everyone is happy, then, except for those of us who have to actually read or write such code. (^& The C function can be made static, in order to hide it from external linkage references, as long as the C++ implementation of my_class::register_motion() can find the C function, window_motion(). Let me say that I find this a bit abhorrent. (^& And in practice, most (probably all) compilers that you have today will accept it if you just register window::cb_motion_func() directly with GLUT. When, if, or why compilers may refuse to accept it, I am not sure. (I can speculate, but that won't do you much good. (^&) However, my understanding is that any C++ compiler is perfectly free to refuse to pass a static class function in lieu of a real C function. But the above, convoluted as it may seem, will still work. Not being a C++ guru, I bowed to the expert wisdom of the people who spend a lot of time fussing over C++ details. --=20 "I probably don't know what I'm talking about." http://www.olib.org/~rkr/ |
From: Nigel S. <ni...@ni...> - 2004-04-23 13:02:38
|
> Is it possible to achieve what I want to do or should I stick with a > global display function. You may interested in using the C++ GlutMaster classes, part of the GLT library: http://www.nigels.com/glt/ This provides a conversion layer: inherit your own application window from GlutWindow, provide implementations of OnReshape, OnDraw, etc as virtual functions. http://www.nigels.com/glt/doc/class_glut_window.html Internally, a bunch of static member functions are used along with a std::map index of the GlutMaster windows to pass events along to. http://www.nigels.com/glt/doc/master_8cpp-source.html Nigel |
From: Steve B. <sjb...@ai...> - 2004-04-23 14:12:00
|
jc...@tu... wrote: > I want to register the callback that is a method of a class, for example: > Is it possible to achieve what I want to do or should I stick with a > global display function. As other people have explained, you can't do this with a regular class member function - but you may be able to 'get away with it' if the function is static. Just to explain the reason for this: When you call a class member function, what actually happens at the machine-code level is that the address of the class object is passed as a 'hidden' first parameter to that function - and that first parameter becomes 'this' inside the function. When you pass the address of a function as a callback, the only thing that's passed is literally that - the address of the function. NOT the address of the object you were referring to. Hence there is no way to know (at the time the callback is invoked) what the address or type of the object was. All we know is the address of the function to call - with no way to know what the address of 'this' should be. Static member functions are just like normal global functions - you can't access 'this' or any non-static members of the class from within those kinds of functions. Hence there is no logical reason why you shouldn't pass those function addresses as callback functions. However, for whatever reasons, the C++ specification says that it's illegal?!? So, compilers that are being pedantic and following the spec to the letter don't allow it - those that are being pragmatic may let you get away with it - hopefully with a WARNING message. Personally, I think you should stick with using global functions for callbacks - that's the only fully portable way. ---------------------------- Steve Baker ------------------------- HomeEmail: <sjb...@ai...> WorkEmail: <sj...@li...> HomePage : http://www.sjbaker.org Projects : http://plib.sf.net http://tuxaqfh.sf.net http://tuxkart.sf.net http://prettypoly.sf.net -----BEGIN GEEK CODE BLOCK----- GCS d-- s:+ a+ C++++$ UL+++$ P--- L++++$ E--- W+++ N o+ K? w--- !O M- V-- PS++ PE- Y-- PGP-- t+ 5 X R+++ tv b++ DI++ D G+ e++ h--(-) r+++ y++++ -----END GEEK CODE BLOCK----- |
From: Nigel S. <ni...@ni...> - 2004-04-23 14:20:00
|
> However, for whatever reasons, the C++ specification says that it's > illegal?!? > > So, compilers that are being pedantic and following the spec to the > letter don't > allow it - those that are being pragmatic may let you get away with it - > hopefully > with a WARNING message. The language lawyers may beg to differ, but I have used statics in this way across many compilers and platforms. There seems to be at least a convention, even if it is not formally demanded by the C++ spec. Nigel |