Path: utzoo!utgpu!watserv1!watmath!att!att!bu.edu!rpi!zaphod.mps.ohio-state.edu!wuarchive!csus.edu!ucdavis!ucbvax!dolphin.aaet.ti.com!ctim From: ctim@dolphin.aaet.ti.com (Craig Timmerman) Newsgroups: comp.windows.x.motif Subject: C++ interface to Motif 1 of 2 (long) Message-ID: <9011161934.AA00403@dolphin.aet_austin> Date: 16 Nov 90 19:34:13 GMT Sender: daemon@ucbvax.BERKELEY.EDU Distribution: inet Organization: The Internet Lines: 187 Since this question popped up again, here is some information on the Univ of Lowell C++ interface to Motif that I have been collecting. I figured others might be interested in this as well. The first part of this is a description/review of the bindings. The second part is a series of messages explaining where you can get the bindings. Maybe if enough people are interested, OSF will stop sitting on this stuff and release it for real. I have been using these bindings for about four months now for some prototype work. Overall I am pleased with how well they work. You can get a better picture of what the binding do by reading the Univ of Lowell paper (see part two for how to get it). The bindings are a set of C++ class wrappers around all of the existing Motif widgets. You refer to the widgets as true C++ classes and all of the Motif and Xt functions are setup as member functions of the classes. Attribute/resource setting is done with set/get member functions. The only time you have to refer to the actual widgets or windows is when you need to go down to the Xlib level. The bindings are very thin. There are only a couple of data members kept by the objects, one is the widget id, the other is a arg list and arg count used by the set/get functions. All set/get functions "queue-up" the attributes to be set/get much just they way you do with Xt. A member function equivalent to XtSet/GetValues is called to flush everything at once. The arg list is currently a fixed size, 100 element array. If I were to go into full production with my code this arg list would need to be changed to an array (preferably a C++ list object) which could grow as needed. 100 elements is a bit excessive for most applications. The delayed set/get action can be avoided by setting a static data member. All get functions take pointers to variables as parameters as a place to store the retrieved value (just like Xt). In many cases it would be preferable to just have the value be the return value of the call. This would be another change I would make to the bindings for production code. The bindings keep a global hash table of widget id to class instance mappings. When you call the object's constructor the mapping entry is put into the hash table. When an object is destroyed the hash table entry is removed. The bindings use the hash table for mapping Xt calls which return widgets to the objects that you want to really use in your C++ program. Callbacks, actions, and event handlers are defined with the aid of macros. The main thing these macros do is provide the two lines of code that access the hash table to convert the widget id normally passed to these functions into a pointer to the proper C++ class instance. This way you can keep the code for the callbacks in C++ and never have to worry about referencing widgets. This is a big difference between the Univ Lowell bindings and the Widget Wrapper Library (WWL) that you may have seen messages posted about. The Widget Wrapper Library doesn't keep a hash table mapping of widgets to objects. Therefore, all of your callbacks, actions and event handlers must be coded in straight C using Xt calls rather than in C++. Being able to access the C++ object in callbacks is even a bigger plus if you have subclassed the widget classes as I have done. The subclasses I have created have allowed me to keep track of additional data I needed for the display and operation on the widgets. This allows me to keep all the data I need right with the widget it pertains to without keeping a whole other data structure like I would in C. Subclassing also allows me to keep the functions which operate on specific objects all packaged together. The subclassing I have done only adds data and function members to the existing objects. It didn't change the basic way the widget works. IF you want to create an whole new widget you must first do the normal Xt subclassing in C, then write the proper C++ binding. The writing of the binding for a new class is straight forward. Several macros help you do it. I created a new binding for the Table widget in very short order. The callbacks, actions and event handlers are written as standalone C++ functions (not member functions). I found this a bit limiting since you either have to make the functions friends of your class or make any extra data members public (this applies only if you subclassed the objects as I did). What I did was write another set of callback, actions and event handler macros to make them call member functions on my subclasses instead of being standalone C++ functions. There are some problems with the bindings. Some of these are nits, others I think are major shortcomings in the software. Most of these could be fixed without a lot of effort. The first thing has to do with the destructors. The only thing the class destructors do is remove the widget<->object mapping from the hash table. The object instance will be destroyed but not the widget itself. What I would expect is if I destroy the object its associated widget gets destroyed too. Now destroying the widget could cause problems if objects were copied (you could have two objects pointing to the same widget). So what the objects need to keep is a widget and a reference count. The reference count is incremented when the object is copied. This way when the object is destroyed the widget is destroyed only if the reference count is 0. There needs to be more convenence functions/classes added. Creating menus is one places where this is nice. I have created a menu item object patterned after some of Doug Young's menu examples. I then added constructors on the menu classes to take a menu item list as a parameter. This way with on simple constructor call for a menu I get the entire menu created. And with one call to the menubar constructor I get the menubar, its menu items and all the pulldowns created. The bindings don't work with UIL (this may be a plus for some people :-) nor do they work with any of the interface builders available today. Getting the bindings to work with UIL would require changes to the MrmFetchHeirarchy call (and its relatives) to have the C++ objects created as well as the widgets. Most of the member functions are real functions. They should be reworked to make them inlines instead. Most of the member functions are 1-2 lines so inlines would just make everything more efficient. Objects are only created for "known" windows. If a widget automatically creates a "hidden" widget there is no C++ object to go with it. An example would be a scrolled window. With the bindings you will have a scrolled window object, but there will be no object that represents the automatically created clip window inside the scrolled window. Normally this isn't a problem until you try to traverse the parent-child heirarchy. Remember with the bindings you work entirely in C++. If I ask for a child's parent I get a pointer to the C++ object representing the parent. A child in a scrolled window is a child of the clip window, not the a child of the scrolled window. Asking for its parent gets a hash table error since there is no C++ object for the clip window. There is a XMString class provided with the bindings. However, this only implements the Motif XmString functionality. It really needs to have more of the functionality that you find with String classes found in class libraries like NIH. One function in particular would be a overloaded (char*) operator so XMStrings could be easily converted to normal char pointers. In contrast to the WWL, the XMString class has member functions to draw themselves, however these functions take the same parameters as the Motif XmStringDraw functions. They should take just the object pointer and figure out the window, display, etc out for themselves. There is no class for fontlists. You must use the stardard Motif mechanisms for dealing with fontlists. There are member functions for gaining access to the widget, window, display, and screen ids/pointers for an object. Most of the time you need these when calling Xlib functions. These member functions are fine, but overloading casting operators like (Widget*), (Screen), and (Display) might be a better way. The naming(capitalization) conventions used for the member functions is inconsistent. If the function represents an Xt function it is called and capitalized just like the Xt functions (sans the beginning Xt prefix). Other functions specific to the bindings start with initial lower case letters. This is a nit, but it's confusing to remember that Parent() is uppercase while display() and screen() are lower. The behind the scenes adding of resources done by some of the Motif composites are not handled properly. The form object is the biggest problem. All of the Attach like resources that are added to form children are incorrectly represented in the bindings by set/get member functions on the form widget. You really want the Attach member function to be on the child, but this member function only makes sense for children of forms. I don't know how to fix this one except by keeping these set/get functions on the form, but make them take the child widget as a parameter. That about wraps up my general comments. I can provide more info if someone has specific questions. I haven't yet sent my nits/shortcomings/bug fixes to OSF, but I will do so shortly. Overall, I have found the bindings to be easy to use. The general programming paradigm still follows Xt/Motif so there is no learning curve there. The bindings allowed me to do what I wanted in my prototype which is to code entirely in C++. However, I truly feel that these bindings are just an interim solution. What is needed is a true C++ class library/API that is not built on any existing C toolkit. This way true subclassing of the widgets to make new widgets would be possible. Hopefully the X consortium working off some kind of an Interviews base will get us in the right direction. My next message summarizes how you might obtain these bindings. ---------------------------------------------------------------------- Craig Timmerman ctim@aaet.csc.ti.com Texas Instruments Austin, TX ----------------------------------------------------------------------