[cffi-devel] unnamed callback (closures?)
Hi, While people certainly appreciate that CFFI provides callbacks (their current state in UFFI or Kenny Tilton's hello-c fork is unknown to me), I wonder why they apply to named functions only. 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? Of course, typical C callbacks provide a void *data pointer, but I'd feel silly if I had to hide some Lisp object within such a pointer. Actually, I don't even know how to map an arbitrary Lisp object this way (it would need some awful int -> obj registration code)! The pattern I'm looking for is (defun my-application (let (x y) ...code... (register-callback 'close-window #'(lambda (data event) (return-from my-application))) (register-callback 'increase-x #'(lambda (data event) (incf x (event->value event)))) (main-loop))) Given the name limitation, I wonder whether the following work-around may be acceptable (using defcallback not at top-level). If yes, I believe the cffi manual should mention it explicitly. Otherwise, it might as well work only in N out of M implementations running cffi, and users would start to write unportable code without knowing. (defun my-callback (closure) (flet foo (defcallback ... ; problem: name is nevertheless global ;; possibly as a macro & backquotes ...))) Or (defun my-application (let (x y) (flet ((quit (data event) (return-from my-application)) (inc (data event) (incf x (event->value event)))) (defcallback close ... :body (quit date event)) (register-callback 'close-window (callback close))))) Possibly this needs a macro&backquote generator, because DEFCALLBACK registers the given name globally in a property list. Thus it disallows running multiple instances of the above. GENSYM might help, but wouldn't this be a kludge? This is quite similar to the (often undocumented) ability to use typical top-level forms in lexical contexts (e.g. the FAQ: is DEFCLASS within a function call etc. possible or not, and what happens). Many libraries don't define the semantics of their macros precisely enough. Regards, Jorg Hohle
On Mon, 19 Dec 2005 16:20:19 +0100, "Hoehle, Joerg-Cyril" <Joerg-Cyril.Hoehle@t-systems.com> said:
Jorg> While people certainly appreciate that CFFI provides callbacks (their Jorg> current state in UFFI or Kenny Tilton's hello-c fork is unknown to Jorg> me), I wonder why they apply to named functions only. Jorg> In CLISP, every closure can be turned into a callback, and this is Jorg> valuable since it allows to retrieve context information out of the Jorg> closure. Is cffi's limitation caused by some implementations? What are the garbage collection semantics of these closures? Presumably the GC can't move them, but when can they be collected? -- Martin Simmons Email: martin@lispworks.com LispWorks Ltd, St John's Innovation Centre TEL: +44 1223 421860 Cowley Road, Cambridge CB4 0WS, England. FAX: +44 870 2206189
"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?
To my knowledge, yes. AFAICT, only SBCL/x86 and CLISP support that. Regarding the behaviour of CFFI:DEFCALLBACK as a non-toplevel form, not only will it set it globally, the callback itself won't be generated at runtime on most Lisp, IIRC. -- Luís Oliveira luismbo (@) gmail (.) com Equipa Portuguesa do Translation Project http://www.iro.umontreal.ca/translation/registry.cgi?team=pt
"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. I mostly develop on SBCL/x86 and ECL, so even if a solution worked on these platforms only, I'd be really happy. --J.
participants (4)
-
Hoehle, Joerg-Cyril
-
Jan Rychter
-
Luís Oliveira
-
Martin Simmons