I wrote:
> On Wed, 01 Feb 2006 09:46:27 +0100, Jan Rychter jan@rychter.com said: > "Luís" == Luís Oliveira luismbo@gmail.com:
Luís> "Hoehle, Joerg-Cyril" Joerg-Cyril.Hoehle@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.
Right. I was actually trying to avoid using that. Evas designers are smart, so they added the "void *data" pointer that gets passed back to callbacks, but this isn't always the case for all libraries.
If it turns out that it isn't possible to have closures as callbacks on the Lisp side, I'll probably do just as you described. Thanks for the suggestion.
Ok, after actually trying this out, there are two major problems:
1. This approach works just fine for adding callbacks, but fails for deleting them. The problem is that the C side insists on identifying callbacks to delete by a function pointer. In this approach all callbacks would get the same function pointer on the C side -- that of the dispatching callback function on the Lisp side. Which means I won't be able to delete them on the C side afterwards.
2. I was actually wrong when I said I knew when the callback would be no longer needed. Not quite sure what to do about this yet. I know next to nothing about finalizers -- can I expect them to be supported?
Apart from a plea for suggestions, this brings me back to my original question -- can we expect any support for anonymous callbacks (closures as callback functions) in CFFI, at least on SBCL to begin with?
--J.