[comp.windows.x] using X11 with C++ callbacks

francis@sunquest.UUCP (Francis Sullivan) (10/20/89)

I would like to be able to use C++ callbacks in X11.  Since this is not
supported, I'm trying to come up with a simple method to simulate this.
For now I just write a C wrapper that calls the correct C++ routine, but
I get the feeling that there is an easier way.

here is an example using wrappers:
class dud {
   char name[8];
  public:
   dud(char *n) { strcpy(name, n);};
   who() {printf ("I am %s\n", name);};
};

dud big("big");
dud dum("dum");

// dummy wrappers
wrap_big_who() { big.who(); }
wrap_dum_who() { dum.who(); }

some_prog() {

   // what I would like
   // XCallMeBack(big.who);  
   // XCallMeToo(dum.who);  

   // what I have to use
   XCallMeBack(wrap_big_who);  
   XCallMeToo(wrap_dum_who);  
}

---
Anyway, a cpp method or a c++ method for dealing with the above is desirable.
Suggestions are welcome,

haynes@gnome5.pa.dec.com (Charles Haynes) (10/20/89)

Use the "this" pointer as the client data in the X callback. Write a
generic wrapper function that takes a class pointer, and a pointer to a
method, and calls that method in that class. The method should have no
other args. Use the wrapper as the callback and the class as the client data.

	-- Charles

dog@cbnewsl.ATT.COM (edward.n.schiebel) (10/20/89)

From article <640@sunquest.UUCP>, by francis@sunquest.UUCP (Francis Sullivan):
> I would like to be able to use C++ callbacks in X11.  Since this is not
> supported, I'm trying to come up with a simple method to simulate this.
> For now I just write a C wrapper that calls the correct C++ routine, but
> I get the feeling that there is an easier way.
[...code deleted...]

I have implemented one solution in SunView, but it seems to be the same 
problem.

First, I have an abstract base class

class dispatchable {
public:
	virtual int doit() = 0;
};

the application derives specific classes from this one to do the
program's stuff.

Now, each Button, Menu_item etc. is given a dispatchable* (either through
some client data mechanism or by creating a class Button which 
encapsulates the X/SunView implementation).  When a button is pressed,
grab its dispatchable* and call doit().

As an aside, I have noticed
to get anything like this to work well takes a lot more time up front
providing support classes etc., but in the end, the application is
so much easier to write.

Hope this is useful, it has worked for me.

	Ed Schiebel
	AT&T Bell Laboratories
	dog@vila.att.com
	201-386-3416

keffer@blake.acs.washington.edu (Thomas Keffer) (10/21/89)

In article <1948@bacchus.dec.com> haynes@gnome5.pa.dec.com (Charles Haynes) writes:
>Use the "this" pointer as the client data in the X callback. Write a
>generic wrapper function that takes a class pointer, and a pointer to a
>method, and calls that method in that class. The method should have no
>other args. Use the wrapper as the callback and the class as the client data.
>

This is essentially the strategy that I have followed with SunView
except that I make the callback routine a static member function of
the appropriate class (in my case, I have defined a ``Panel'' class
that manages a window).  The callback routine looks something like:

void
Panel::someButtonCallBack(Panel_item p, int value, Event *e)
{
	PanelClient* this_client = panel_get(p, CLIENT_DATA);
	this_client->memberFunctionYouWantToCall(value);
}

Or something like that.  Here, PanelClient is the object being
maniupulated on behalf of the window. The advantage of using a
static member function is to further encapsulation while giving you
access to the appropriate member functions and variables.

An example is available via anonymous ftp from
sperm.ocean.washington.edu in file ~ftp/pub/spinup.tar.Z

-Tom Keffer

Rogue Wave
P.O. Box 85341
Seattle Wa 98145-1341
(206) 523-5831