home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!cs.utexas.edu!ut-emx!ccwf.cc.utexas.edu!filo
- From: filo@ccwf.cc.utexas.edu (John Filo)
- Newsgroups: comp.windows.open-look
- Subject: Re: Q: C++ and callback problems.
- Message-ID: <FILO.92Aug27190611@doc.cc.utexas.edu>
- Date: 28 Aug 92 00:06:11 GMT
- References: <1737@ernohb.UUCP> <1992Aug24.171121.27530@isy.liu.se>
- Sender: news@ut-emx.uucp
- Organization: The University of Texas at Austin
- Lines: 120
- In-reply-to: svan@isy.liu.se's message of 24 Aug 92 17:11:21 GMT
-
- In article <1992Aug24.171121.27530@isy.liu.se> svan@isy.liu.se (Jonas Svanberg) writes:
-
- > I'm using xview myself and have given up the idea of having a nice
- > and pure objectoriented system without old-c-style functions :-)
-
- I've been able to use c++ with xview with some success, although the
- way I went about it is sort of a kludge, and after reading Steve's
- article I realized that this method will only work on member functions
- that aren't virtual, so that might limit it's usefulness.
-
- Below is a copy of a message I sent someone a few months back
- addressing this same issue. Since I missed the original poster's
- question, I don't know if this will help you since the details are
- specific to xview, but I imagine a similar scheme could be worked out
- with most other toolkits.
-
- =========================================================================
- I've used C++ with xview before on a Sun. I only had two problems.
- First, C++ requires prototypes for all functions. If your header
- files don't handle this correctly, then you'll have to write prototypes
- yourself, which can be a real pain in the ass. The include files that
- come with Sun's xview handles this correctly so it wasn't really much of
- a problem for me, except for tha fact that one of the include files had
- to be modified in order for it to compile correctly.
-
- The second problem is more serious and has to do with using member
- functions as callback procedures. For example lets say you have an object
- that contains a Canvas and you want to use one of the member functions for
- it's repaint procedure. When xview invokes the repaint procedure, it will
- pass the arguments (Canvas, Xv_window, Display...) as if it were a regular
- C function. However, C++ expects an undeclared, implied "this" pointer to
- passed as the first parameter. This has the effect of shifting all the
- parameters one place to the left, with the Canvas id equal to the
- Xv_window id, the Xv_window id equal to the Display pointer and so on.
- The "this" pointer ends up being set to Canvas id.
- There are several solutions to this problem.
-
- 1. Don't use member functions for callbacks.
- This isn't a very good solution since it reduces the usefullness
- of C++.
- 2. Use a static member function that calls a non-static member
- function. This way, all the callback stuff is encapsulated
- inside the class containing the callback. However, in order
- for this to work, the static member function must know
- which object to use when invoking the non-static member
- function. This can be accomplished with the following:
-
- // comewhere in cObject initialization
- xv_set(xvObject,
- XV_KEY_DATA, KEY_THIS_PTR, &cObject,
- ???_PROC, staticCallback,
- NULL);
-
- then, inside the static callback, you can get the object pointer
- as follows:
-
- staticCallback(XVObject xvObject, /* other args */)
- {
- CObject *cObject;
-
- cObject = (CObject*) xv_get(xvObject, XV_KEY_DATA, KEY_THIS_PTR);
- cObject->nonStaticCallback(xvObject, /* other args */);
- }
-
- This is kind of messy, but at least all the mess is hidden in the class
- definition. My only complaint about this method is that you have to
- define a static and non-static function for every callback.
-
- 3. Use a technique similar to the one above, but without the static member
- function.
-
-
- // somewhere in cObject initialization
- xv_set(xvObject,
- XV_KEY_DATA, KEY_THIS_PTR, &cObject,
- ???_PROC, nonstaticCallback, //a weird case is required
- NULL); //here, but I'll have to
- //look it up.
-
- then, inside the nonstatic callback,
-
- // note the lack of the XVobject arg, it's stored in the "this" ptr;
- nonstaticCallback(/* other args */
- {
- XVObject xvObject = (XVObject *) this;
- this = xv_get(xvObject, XV_KEY_DATA, KEY_THIS_PTR);
- ...
- // procede as you would in any c++ member function
- }
-
- I prefer this method, since all the work is in one place.
- However, the assignment to the "this" pointer is probably
- considered a no-no, and may even be obsolete. I used
- AT&T's CC, version 2.0, and I think the mention something
- about it being kept in there for backwards compatability,
- but at some point would be removed from the language,
- so this may be unwise. An alternative is to the following
- in the callback
-
- nonstaticCallback(/* other args */)
- {
- XVObject xvObject = (XVObject *) this;
- CObject *me = xv_get(xvObject, XV_KEY_DATA, KEY_THIS_PTR);
- ...
- // now all members must be prepended with me->. this is
- // very ugly and error prone, and probably not a good idea.
- }
-
- If you want ensured compatability in the future, I would probably
- recommend method 2, although I use the 3rd method.
-
- Hope this helps,
-
- John Filo
- filo@ccwf.cc.utexas.edu
-
-
-
-
-
-