[cffi-devel] Re: unnamed callback (closures?)

Martin Simmons martin at lispworks.com
Wed Feb 1 10:33:38 UTC 2006


>>>>> On Wed, 01 Feb 2006 09:46:27 +0100, Jan Rychter <jan at rychter.com> said:
>>>>> "Luís" == Luís Oliveira <luismbo at gmail.com>:
>  Luís> "Hoehle, Joerg-Cyril" <Joerg-Cyril.Hoehle at t-systems.com> writes:
>  >> In CLISP, every closure can be turned into a callback, and this is
>  >> valuable since it allows to retrieve context information out of the
>  >> closure.  Is cffi's limitation caused by some implementations?
> 
>  Luís> To my knowledge, yes. AFAICT, only SBCL/x86 and CLISP support
>  Luís> that.
> 
>  Luís> Regarding the behaviour of CFFI:DEFCALLBACK as a non-toplevel
>  Luís> form, not only will it set it globally, the callback itself won't
>  Luís> be generated at runtime on most Lisp, IIRC.
> 
> I've just ran into the same problem. I really really need closures as
> callbacks. I've tried the naive approach:
> 
> (defmacro object-event-callback-add (obj type function)
>   `(foreign-funcall "evas_object_event_callback_add"
>     :pointer ,obj
>     callback-type ,(foreign-enum-value 'callback-type type)
>     :pointer (get-callback (defcallback ,(gensym "CB")
> 			       :void
> 			       ((data :pointer) (cb-e evas) (cb-obj object) (cb-event :pointer))
> 			     (funcall ,function cb-e cb-obj cb-event)))
>     :pointer (null-pointer)))
> 
> ... but that's a half-baked solution with too many limitations and only
> works in a simple example that you run once.
> 
> What are the problems with unnamed callbacks? My guess was that they
> will never get garbage-collected, but how about storing all of these in
> a table somewhere and explicitly freeing them after they are no longer
> needed? In my case I do have a way of finding out when a callback is no
> longer needed, and I suspect this is the case for many other
> applications.

The function evas_object_event_callback_add already makes a closure -- on the
C side.  You can pass arbitrary data as the last argument and it will be
passed to your callback, so you can make data an integer index into an array
of Lisp closures.  Since you know when a callback is no longer needed, you can
recycle the ids quite easily.

It is easy to wrap this up in a function to avoid the code looking like C
every time you add a callback.

__Martin



More information about the cffi-devel mailing list