From: wnielsen@nosun.West.Sun.COM (Walter Nielsen - SUN Portland)
Newsgroups: comp.windows.open-look
Subject: Re: Q: C++ and callback problems.
Date: 27 Aug 92 17:25:44 GMT
Article-I.D.: nosun.1992Aug27.172544.12548
Organization: Sun Microsystems, Beaverton Oregon

Its not all that complicated, cfront adds an hidden parameter to all member
function calls.  Namely the 'this' pointer.  This doesn't happen in static
functions but of course static member functions have their limitations.
The easiest way is to define callbacks as regular functions and make
them friends of your class.   Or alternatively have the callback be
regular functions which call the object's member function which does
the work.   Typically one would use the client_data field to get
the object's 'this' pointer in the callback.

Object-oriented purists may object but this approach works.

-Walter Nielsen
Sun Microsystems

> 
> > I have problems with c++ and callbacks. My intention was to create a window
> > class which contains one or more callback functions, implemented as class
> > methods. This doesn't work properly. Somewere along the way ( probably down in
> > Xlib ) the callback parameters are LOST i.e. if the callback funktion is NOT
> > declared as a static. This is not what i want but it seems to be the only way 
> > to overcome this strange behaviour. The static function will be common to all
> > instances of this object. I will not be able to identify from wich instance the
> > callback originated. I have tried this in OLIT and XVIEW as well and found the 
> > same problems. I have tried it using X11R4 along with SUN's c++ compiler on a 
> > SUN (IPX).  Here comes a simple sample program that works, but not the way i 
> > want (without static).
> 
> I have had the same problem in a couple of projects now...
> 
> I have some comments:
> 
> 1. In your example program you choose to send the pointer-to-memberfunction
>    as a callback. These pointers are *not* ordinary c-pointers in that they
>    may not even occupy the same space as an ordinary pointer. Usually (I
>    think) it is some sort of structure. There are no casts to ordinary 
>    pointers to functions which are garanteed to work. So xview/olit gets
>    a structure but thinks it's an ordinary functionpointer. The pointer
>    it gets is more likely to point to a jumptable or something... It isn't
>    a problem with XLib or something. The problem is a difference of types.
>  
> 2. Also these pointers do not contain any instance-information, so even if the
>    package knew how to handle the pointer-to-memberfunction, (It had to be a
>    C++-package for that) it doesn't know how to deliver the hidden <this>-
>    parameter which every nonstatic memberfunction need. So when registering 
>    a callback, the object too must be sent somehow. Strong typing doesn't 
>    make this an easy task. The class of the object and the type of the
>    pointer-to-member must agree in a certain way.
>    
> 3. So, what one need is to be able to extract a pointer-to-member-of-specific-
>    instance. The designers of C++ have deliberately chosen not to have such
>    "first class objects" in their language. For now (ever?) it isn't possible
>    to implement callbacks in C++ the way you (and me) would like. Some
>    have tackled this problem. I e Borlands Turbo C++ for windows have some
>    weird extension to the language that enables direct calls to specific
>    objects. I don't like that ;-(
> 
> 4. With pure C++-toolkits one often overcome this problem by making one's classes
>    inherit from the toolkitclasses. Since some of the memberfunctions in
>    these classes are virtual you could shadow those and receive calls in
>    that way. I e you make your own button inherit from the toolkit Button and
>    defines your own buttonPressed()-memberfunction. See the FAQ for such
>    toolkits.
> 
> CONCLUSION:
> 
> In C++, as it is defined, it's impossible to have callbacks the way which
> seems natural. You (and I) will have to do with these static functions,
> which of course could extract the object from some sort of userassignable
> data in the toolkit-object, and call the appropriate method in the object.
> Such static functions would act as some sort of stubs.
> Maybe one should let the static function itself be the real handler
> in the object, but then you have to write xxxx. in front of every
> membercall...
>      
> References:
>     
>    "The annotated C++ reference manual" (AT&T 1990)
>     Margaret A. Ellis & Bjarne Stroustrup
>    5.4 page 70-71 for a discussion on pointer-to-memberfunctions
>    4.8 page 38-39 casting pointers to members.
>    There is a 2nd ed. out now, I guess these side# are obsolete...
> 
> ---
> 
> I'm using xview myself and have given up the idea of having a nice
> and pure objectoriented system without old-c-style functions :-)
> 
> --------------------------------------------------------------
>  Jonas Svanberg
>  Department of Electrical Engineering
>  Linkvping University
>  S-581 83 Linkvping, Sweden             Email: svan@isy.liu.se
> --------------------------------------------------------------
> 
> 
> 
-- 

              /\        
             \\ \       Walter Nielsen
            \ \\ /      Sun Portland - "Where the trees grow bigger"