Jimmy Johnson wrote: > I have a problem for which I hope one of you c experts have a solution. I > must write an openGL application and am required to use C or C++ and glut. I > come from an object-oriented mindset, therefore I gravitate toward C++. Now > glut requires C-functions to be passed for the callbacks, but there is a > mismatch between the type of a "c function" and a "c++ member function". I > was told, "Just hack something together with C." Well, that goes against my > grain. I want all the benefits that come with OO, especially reuse. > (Besides, I have to be able to read my own code, and from what I see in the > example c code I've been given, that is hard to achieve in C.) > > Caveat: I am new to C so my knowledge of the syntax, especially with > pointers and pointers to functions, is lacking, so I will try to use > pseudo-code in hopes that someone can clean it up if what I want to do is > possible. > > With that out of my system let me use one of the glut features as an example. > > glutReshapeFunc (onReshape) tells glut to call onReshape when the window size > changes. onReshape must have two int arguments: > onReshape (int aHeight, int aWidth) > > Ideally, I would like to do this in main(): > > displayable myWin; > // where displayable is a C++ object whose class > // has method `onReshape' taking two int arguments. > glutReshapeFunc (myWin::onReshape); > > better yet, in the constructor for displayable: > displayable() { > glutCreateWindow(); // etc. > glutReshapeFunc (onReshape); > }; > > but this will not work because of the type mismatch as mentioned above. So I > do this: > displayable* myWin := NULL > void myWinReshapeWrapper (int h, int w) { > myWin->onReshape; > }; > > int main(…) { > // initialize glut > glutCreateWindow("This creates a window"); > // … > myWin = new displayable; > glutReshapeFunc (myWinReshapeWrapper); > > This is a problem because I [and any user of my class] will have to have a > reference to and write a "reshape wrapper" for every single displayable he > wants. > > > So, given that > 1) I can't use C++ member functions in a C callback > 2) The "wrapper" method works, but is not scalable > Is there a way to: > Have a method (c++ member, or a c-function included at the top of the > class "displayable"), called in the constructor that can do this wrapping > automatically. Something like: > > function* makeWrapper (displayable* dis, function* func) > // given reference to a displayable and some function > // return a new function that simulates "dis->func" > > And then in the constructor: > displayable() { > glutCreateWindow(); > f = makeWrapper (this, onReshape) > glutDisplayFunc (f); > > To boil it down, I want to create new functions to be used as callbacks which > will call a c++ method on the correct object. > > To anyone who has read this far, I thank you. > > Best regards, > > Jimmy J. Johnson
I used GLUT once upon a time. Pain in the butt and really not designed for C++. It was an OpenGL + GLUT + GLUI app. They are the "poor-man's toolkit" for OpenGL. The main issue you are having is associating an object with a function that doesn't support transmitting the object pointer (i.e. it doesn't allow 'this' to be passed). GLUT, if I recall, pretty much assumes two things: Single thread, single instance. Your 'makeWrapper' idea is called a "thunk". It can be done but it is an ugly solution (yet, at the same time, it is somewhat elegant since C++ offers no really good way to accomplish this sort of thing natively). Thunks are generally written in platform and compiler-specific assembler. I don't recommend this approach (using static member functions is usually the "correct" way). But if you want to do the thunk route, you build up a string of assembler opcodes, put them in an aligned executable page of memory (VirtualProtect()), and flush the processor instruction cache (FlushInstructionCache()). Then return a pointer to the start of the dynamically generated "function". In essence, your "function" will look like: mov ecx, this; jmp actual_function_address; Or whatever your compiler requires for 'this' to work properly (ecx is usually for 'fastcall'). It could get ugly if you have to modify the stack but the 'this' pointer is _usually_ the last thing put on the stack: push esp, this; jmp actual_function_address; In both cases, 'this' is the instance of your class and 'actual_function_address' is the address of the method you want to call. The above code is targeting the Intel architecture and is completely untested other than recalling from the only time I've ever done thunking. Besides the already big caveats mentioned, thunks also have another big downside: Debuggers get lost. You can't stick a breakpoint inside the thunk itself and most debuggers will generally get lost in whatever the actual callback is (the call stack is usually screwy inside the function). After all, thunks are rare and unexpected. You are probably better off writing function wrappers. They work and are cross-platform/compiler. If you want to have something more "reusable", look into the 'virtual' keyword. You write a base class one time that calls derived functions (in a derived class) IF they exist. The base class does all the evil stuff you are wanting to disappear from your code that is ugly and the derived class is just the nice, clean code you are after. -- Thomas Hruska CubicleSoft President Ph: 517-803-4197 *NEW* MyTaskFocus 1.1 Get on task. Stay on task. http://www.CubicleSoft.com/MyTaskFocus/ ------------------------------------ To unsubscribe, send a blank message to <mailto:c-prog-unsubscr...@yahoogroups.com>.Yahoo! Groups Links <*> To visit your group on the web, go to: http://groups.yahoo.com/group/c-prog/ <*> Your email settings: Individual Email | Traditional <*> To change settings online go to: http://groups.yahoo.com/group/c-prog/join (Yahoo! ID required) <*> To change settings via email: c-prog-dig...@yahoogroups.com c-prog-fullfeatu...@yahoogroups.com <*> To unsubscribe from this group, send an email to: c-prog-unsubscr...@yahoogroups.com <*> Your use of Yahoo! Groups is subject to: http://docs.yahoo.com/info/terms/