Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!sdd.hp.com!decwrl!aurora!jp From: jp@aurora.com (Jorge Phillips) Newsgroups: comp.lang.c++ Subject: Re: Calling a C++ routine as an X11 libXt callback function Summary: An approach on how to interface C++ (g++) and Xt code Keywords: g++, Xt, X11R4 Message-ID: <1990Aug20.230100.601@aurora.com> Date: 20 Aug 90 23:01:00 GMT Organization: The Aurora Group Lines: 152 In article <8271@ncar.ucar.edu> vanandel@stout.atd.ucar.edu (Joe Van Andel) writes: >I am writing an application that uses the Athena widget set, but I would like >to write this application in C++ (using g++), if possible. > ...some stuff re. Interviews. >The biggest hassle I see with using C++ and a non C++ toolkit is that >of using callbacks. Since the callbacks are designed to be C >functions, how can I possibly invoke C++ functions, particularly if I >want to invoke the method of a given object? If I have to, I'll write a bit >of "glue" in "C", but I don't know how to do it. Obviously, if writing the >glue is too tedious or difficult, using C++ just may not be worth the hassle. > > ...more stuff... >-- > Joe VanAndel Internet:vanandel@ncar.ucar.edu I had the same problem a while ago while writing g++ code that used Xt widgets and library calls. Initially I thought of rewriting the Xt, Xlib, Xmu, etc. headers as C++ headers, like some people have suggested. Since I did not know of `protoize' and `unprotoize' yet, I gave up on this alternative and decided to use the glue approach. Basically the idea is to write your C++ program in such a way that after it performs all the necessary C++ object initializations, it relinquishes control through glue to an X main program. This program creates all widgets, establishes all callbacks (including those that go to C++ through glue), and enters its event loop, thus effectively driving the application from here on. Here is a code skeleton of how I implemented callbacks to g++ functions following this idea, using a glue file. Admittedly, the resulting code is not as clean and elegant an interface as I would like it to be, but it works quite fine! If you define a lean (i.e. well localized) interface between your C++ program and your X code, the glue file turns out to be quite small. E.g. for a 7,000+ line g++ program using a substantial number of widget classes and Xt and Xlib operations, the glue code turns out to be only 100 lines of includes and glue procedure definitions. I would appreciate any suggestions for a better (different, improved, etc.) interface mechanism. Has anybody tried protoizing X11 headers and writing ONLY c++ code that accesses Xt wdigets and primitives? -Jorge Encl: ========================== X INTERFACE (x.c) /* Xt-based client * Code skeleton */ #include /* all Xt, Xlib, Xmu, Xaw, etc. headers needed */ Widget w1; Widget w2; .... /* declare all widgets */ void W1Callback(Widget w, caddr_t cl, caddr_t cd) { /* here goes code that accesses widgets and X stuff */ XGlueFoo(..args..); /* call c++ callback through glue code */ /* here goes any post-callback code, if needed. */ } /* X driver portion main function */ int XMain(int argc, char** argv) { /* local decls */ top = XtInitialize(...); w1 = XtCreateManagedWidget("w1", ...someWidgetClass..., top, NULL, 0); XtAddCallback(w1, XtNcallback, W1Callback, 0); /* ...more Xt stuff... */ XtRealizeWidget(top); XtMainLoop(); } ========================== GLUE BETWEEN C++ and Xt CODE (glue.cc) #include ...global header defs... #include ...c++ headers needed by glue fns ... #include "glue.h" // declare below all C++ variables and procs used by glue extern Class1* a; // handle to some object used by glue extern void SomeCCProc(); // maybe friend of some classes and objects extern CC_Class someCCObject; // will use this in callback extern "C" { /* declare here all x.c vars and procs used by glue */ extern int XMain(int, char**); extern void XDoSomethingOnScreenFromCC(); /* called from C++ side */ /* declare here all C procs called from X interface */ void XGlueFoo(..arg decls..) { /* This links to c++ callback code. Notice that objects used must be declared in included headers or above */ someCCobject->SomeMethod(arg1, arg2, ... argK); /* the c++ callback */ } someCType XGlueReturnValue(..arg decls..) { return anotherCCobject->AnotherMethod(...args...); /* returns val to x.c */ } /* declare here C++ procs that call the X interface, such as XMain */ int XGlueXMain(int argc, char** argv) { return XMain(argc, argv); // start Xt portion of system } }; // end extern C ========================== C++ CODE (main.cc) // Main C++ program #include ...c++ headers... // include the glue header file for communication extern "C" { #include "glue.h" }; CC_Class someCCobject; // to be used by XGlueFoo() int main(int argc, char** argv) { ...set up world... ...perform any preliminary C++ processing... return XGlueXMain(argc, argv); // relinquish control to X through glue } -- jp@aurora.com --- Sic itur ad astra.