[Ecls-list] Callbacks in ECL

Juan Jose Garcia Ripoll jlr at mpq.mpg.de
Wed Oct 12 06:19:02 UTC 2005


On Wed, 2005-10-12 at 14:41 +0200, Goffioul Michael wrote:
> > Hi,
> > 
> > I have committed a rather simple implementation of callbacks for ECL,
> > with a syntax resembling that of CFFI.
> > 
> > Unfortunately, and in contrast to ECL's SI::CALL-CFUN this
> > implementation does rely on the compiler. I thought about trying
> > something different but that would be far too difficult, as it would
> > involve dynamically creating assembly code, plus allocating regions of
> > executable memory, etc, etc.
> 
> In attachment, you'll find my trial at implementing dynamic callbacks
> under x86/MSVC. I tested it on simple cases and it seems to work OK. One
> thing that made this implementation easy is that malloc'ed memory is
> directly executable on this platform.

I am not sure I understand this. The problem of callbacks, as I
understood it, is to produce _arbitrary_ C functions with any given
signature. I.e. functions like
	int mycallback(int a, int b)
	void mycallback(void *closure_data)
	...
For this you need the type of code I committed already, and this is
precisely the type of callbacks that CFFI produces (and now also ECL)

A different problem are creating event handlers. To be more precise,
this happens in the context of C/C++ event-driven programs, where the
user calls a library function and supplies both a pointer to a function
and some data that the function is to be invoked with. In the C/C++
world this is the closest one gets to closure. This can also be solved
without the need of dynamically creating assembler code. One would
simply write once and for all

	(defcallback general-callback :void ((f :object))
	   (funcall f))

Assuming the library function is called "window_loop" and it has a
signature like

	void window_loop(int event, void (*f)(void *data), void *data)

one would simply invoke it as in

	(si::call-cfun "window_loop" :void (:int :pointer-void :object)
	     (list +CLOSE-WINDOW+ (callback f)
		 #'(lambda () (print "Goodbye!")))

Finally, a different and contorted version of the previous problem would
be to produce a single function pointer that is to be called and which
automagically finds out the data it requires. The code you supplied does
indeed this and one also finds similar things in the FFCALL library. But
I wonder if this is actually needed in real life. I have never
personally found this in my life because C/C++ programmers typically
know that such a construct is probably not reentrant. Am I wrong? :-/

Regards,

	Juanjo






More information about the ecl-devel mailing list