[C++-sig] Marshalling Callbacks

William Trenker wtrenker at hotmail.com
Mon Dec 23 02:01:43 CET 2002


(This turned out to be a bit lengthy, but I have tried several approaches 
without success.  It is obvious that I am missing a key BPL concept (or two, 
or three).  I need to get this right because there are many places in FLTK 
that use this callback mechanism.)

What I'm trying to figure out is the recommended / design-intended method 
for marshalling callbacks between the python layer and C++?

3-rd party GUI libraries, like FLTK, handle external events (such as mouse 
clicks) with a callback mechanism that is something like this very sketchy 
pseudo-code;

-------------------3rd Party----------------------
class Widget {     //low-level GUI object
	void callback(void* func, void* data) {
	    //save callback address and data pointer
		cbfunc = func;
		cbdata = data;
	};
	void run() {
	    //wait for mouse clicks
		when (mouseClicked) (*cbaddr)(cbdata);
private:
	void (*cbfunc)(void*);
	void* cbdata;  //opaque structure from GUI's perspective
}

Class Button : public Widget {
public
	Widget();
	//NB: no callback() or run() defined here
}
---------------------------------------------------

An application, in C++, does something like this:

Class A {
public:
	A() { b = new Button(); };
	void onClick(void* appInfo) {
		//gets called by Widget::run
		cout << "Mouse was clicked!";
	};
	void execute(info) {
		b->callback(&onClick,&info);  //(1)
		b->run();                     //(2)
	}
private:
	Button* b;
	whatever info;
}

At (1) the applicaton registers the callback member function so that, at 
(2), Widget::run knows what to call when the mouse is clicked.
---------------------------------------------------

The python equivalent might be:

import ext
class A:
   def __init__(self):
      self.b = ext.Button()
   def onClick(self,appInfo):
      print "Mouse Clicked!"
   def execute(self,info):
      self.b.callback(self.onClick,info)
	  self.b.run()
---------------------------------------------------

When I initially set out,in blissful ignorance, to wrap the above API for 
Python, the following seemed to be the logical implementation:

class_<Widget, boost::noncopyable>("Widget");
class_<Button, bases<Widget>, boost::noncopyable>("Button")
   .def("callback", &Widget::callback)
   .def("run", &Widget::run);

But, of course, the .def("callback"...) is not as simple as wrapping an int 
or a char*. It needs some additional options or features to marshall the 
callback mechanism so that a Python method (or function) gets saved and then 
eventually invoked by the 3rd-party C/C++ software.

Where I'm stuck is what that marshalling mechanism looks like.  I'm aware of 
call<> and call_method<>; I've tinkered with handle<>'s and object's;  I've 
read the docs and studied the examples.

Any advice or assistance is very greatly appreciated.

Thanks for helping,
Bill



_________________________________________________________________
The new MSN 8: smart spam protection and 3 months FREE*.  
http://join.msn.com/?page=features/junkmail&xAPID=42&PS=47575&PI=7324&DI=7474&SU= 
http://www.hotmail.msn.com/cgi-bin/getmsg&HL=1216hotmailtaglines_smartspamprotection_3mf





More information about the Cplusplus-sig mailing list