109) How can I have a C++ member function in a callback?

[Last modified: October 93]
Answer: There are three common user problems with C++ callbacks.  First, make
sure you use the correct function prototype for the function declarations.
Second, the callback function must be declared as a static member of the
class.  Third, when registering it with XtAddCallback(), you must use its full
signature.  For example: (Ken Lee klee@synoptics.com)


    class MyClass {
        ...
        void createWidgets();
        static void myButtonCB(Widget, XtPointer, XtPointer);
        ...
    };
    void MyClass::createWidgets() {
        ...
        w = XtCreatePushButton(...);
        XtAddCallback(w, XmNactivateCallback, &MyClass::myButtonCB,
            (XtPointer) this);
        ...
    }
    void myButtonCB(Widget w, XtPointer clientData, XtPointer callData) {
        MyClass *myclass = (MyClass *) clientData;
        ...
    }

Note that the "this" pointer is used as the client data.  This technique is
popular, but not required.


Motif++ has a nice tutorial summarising mechanisms (this is available
separately by email from Ronald van Loon (rvloon@motif.hacktic.nl)). Doug
Young's book deals extensively with one of these. The problem is that you
don't get the object when you just use the function as a callback.  You need
to pass the object as a pointer through as the client_data.  (use "this" as
the client_data.) Then you can retrieve the object's address, and dereference
from there. For example (Leo O'Donnell, Email: leo@avs.com),


    class MyButton {
      public:
                MyButton (Widget parent, const char *name) {
                    _button = XtVaCreateManagedWidget (
                        name, xmPushButtonWidgetClass, parent, NULL, 0);
                    XtAddCallback (
                        _button,
                        XmNactivateCallback,
                        &MyButton::activateCB,
                        (XtPointer) this);
                }
                ~MyButton () { XtDestroyWidget (_button); }
      private:
        Widget  _button;
        static  void activateCB (Widget, XtPointer, XtPointer);
    };

    void MyButton::activateCB (Widget, XtPointer thisBtn, XtPointer)
    {
        MyButton *btn = (MyButton *) thisBtn;

        // OK you've got the button instance now. Do some stuff with it!
    }
Go Back Up

Go To Previous

Go To Next