>> * Sean McNamara <gnax@...> [2008-05-26 11:39:39 -0500]:
>> I'm trying to pass a callback defined in Lisp to the C function
>then you need to defined the function using defun,
>then define the corresponding callback using def-call-in,
Superfluous, esp. when using dynamic libraries.
>then define the callback
>argument in the def-call-out NOT as a c-pointer, but as a c-function
>with the type appropriate for the def-call-in.
>see also example 32.6.
[*] Lambda do also work in place of DEFUN.
However I strictly recommend DEFUN for a simple reason, which if I had
time, I'd try to elaborate upon in the documentation:
Callbacks (C function calling Lisp function) create so-called
A trampoline is a piece of C code which knows how to call a particular
Lisp function. The C pointer that the foreign library receives is the
pointer to this piece of code.
These are NOT subject to garbage collection, as there's no protocol to
tell the garbage collector when a given callback is not needed anymore,
unlike Lisp objects.
With a callback to a DEFUN, this is mostly harmless, as the defun is
likely never redefined.
With callbacks to LAMBDA, this can become an issue, as in typical
situations, lambdas are produced dynamically, e.g. inside a loop, so
thousands of trampolines may be generated.
You can use FFI:FOREIGN-FREE to free the trampoline associated with a
That's why I recommended explicit creation and management of
FOREIGN-FUNCTION objects in some past messages.
When you pass a lambda to a def-call-out with a parameter of type
c-function, such a trampoline is allocated, but you do normally not get
hold of the associated trampoline objects. That's why you cannot
(trivially) free it.
To free it, you'd need to receive a corresponding foreign-function
object from the FFI.
That's why I find it easier to create the #<FOREIGN-FUNCTION> object
first, pass that to the DEF-CALL-OUT (the one registering your
callback), and eventually, when the application is done, call
FFI:FOREIGN-FREE on all the callbacks that were used
Again, when the callback is a DEFUN, I wouldn't bother freeing it.
BTW, this issue is not particular to CLISP. Every language and
implementation must (somehow) deal with the issue. The difficulties hint
at why there's no anonymous (lambda) callbacks in CFFI: they may not be
available in every implementation.
Note that different trampolines are created for the same Lisp function
when the foreign type specification differs: each trampoline corresponds
to one particular signature of the Lisp function.
E.g. (c-function (:arguments (foo c-pointer)))
and (:arguments (foo (c-function ...))) differ.