From: tvtjet@eua.ericsson.se (Jorgen Eriksson)
Subject: Q: C++ and callback problems.
Organization: Ellemtel Telecom Systems Labs, Stockholm, Sweden
Date: Fri, 21 Aug 1992 13:43:05 GMT

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 would very much appreciate if someone has an explanation to this behaviour, or
a nice'n'clean solution to overcome it. Email me.

aTdHvAaNnKcSe

	/Jorgen ( Jorgen.Eriksson@eua.ericsson.se )

******************* START of CODE *******************************

#define	XTFUNCPROTO
#include <stdio.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
 
/*
        Class definition:
                                */
class   Win{
public:
        Win(Widget);
private:
        ///////////////////////////////////////////////////////////////////////
        //
        // If ButCB() not is declared static, all parameters is lost (widget id,
        // pointers to client and call data).
        //
        // Remove 'static' and the program will result in a bus error.
        //
        ///////////////////////////////////////////////////////////////////////
        static void     ButCB(Widget, caddr_t, caddr_t);
 
        Widget  push_b1;
        Widget  push_b2;
};
 
/*
        Code:
                        */
void
Win::ButCB(Widget w,caddr_t client_data,caddr_t call_data)
{
        Arg     args[10];
        Widget* w1 = (Widget*) client_data;
        XmString xms1, xms2;
 
/*
        This callback function toggles button labels.
                                                        */
        XtSetArg(args[0], XmNlabelString, &xms1);
        XtGetValues(w, args, 1);
        XtSetArg(args[0], XmNlabelString, &xms2);
        XtGetValues(*w1, args, 1);
 
        XtSetArg(args[0], XmNlabelString, xms2);
        XtSetValues(w, args, 1);
        XtSetArg(args[0], XmNlabelString, xms1);
        XtSetValues(*w1, args, 1);
}
 
Win::Win(Widget parent)
{
        Widget  work_area, form_dia;
        Arg     args[10];
 
        form_dia = XmCreateFormDialog(parent, "Nonsense", args, 0);
        XtManageChild(form_dia);
 
        work_area = XmCreateWorkArea(form_dia, "mw", args, 0);
        XtManageChild(work_area);
 
        push_b1  = XmCreatePushButton(work_area, "Hello", args, 0);
        XtManageChild(push_b1);
        XtAddCallback(push_b1, XmNactivateCallback,(XtCallbackProc)&Win::ButCB,
            (caddr_t)&push_b2);
 
        push_b2  = XmCreatePushButton(work_area, "World", args, 0);
        XtManageChild(push_b2);
        XtAddCallback(push_b2, XmNactivateCallback,(XtCallbackProc)&Win::ButCB,
            (caddr_t)&push_b1);
}
 
/*
        Tiny main:
                        */
main(int argc, char** argv)
{
 
        Win*    win;
        Win*    new_win;
        Widget  app_shell;
        int     n;
        Arg     args[10];
 
        app_shell= XtInitialize(argv[0],"",0,0,(Cardinal *)&argc,argv);
 
        n = 0;
        XtSetArg(args[n], XmNheight, 1); n++;
        XtSetArg(args[n], XmNwidth, 1); n++;
        XtSetArg(args[n], XmNmappedWhenManaged, False); n++;
        XtSetValues(app_shell, args, n);
 
        /* Two separate instances is created: */
        win = new Win(app_shell);
        new_win = new Win(app_shell);
 
        XtRealizeWidget(app_shell);
        XtMainLoop();
}
*************** END of CODE ***********************