Next: Optimizing Type Translators, Previous: Defining Typedefs, Up: Foreign Types
Type translators are used to automatically convert Lisp values to or
from foreign values. For example, using type translators, one can
define a boolean type which converts a Lisp generalized boolean
(nil
vs. non-nil
) to a C boolean (zero vs.
non-zero).
We created the my-boolean
type in the previous section. To
tell CFFI how to automatically convert Lisp values to
my-boolean
values, specialize the generic function
translate-to-foreign
using an eql-specializer with the
name of your type, in this case the symbol my-boolean
:
;;; Define a method that converts Lisp booleans to C booleans. (defmethod translate-to-foreign (value (type (eql 'my-boolean))) (if value 1 0))
Now, when an object is passed as a my-boolean
to a foreign
function, this method will be invoked to convert the Lisp value to an
integer. To perform the inverse operation, which is needed for
functions that return a my-boolean
, specialize the
translate-from-foreign
generic function in the same manner as
above:
;;; Define a method that converts C booleans to Lisp booleans. (defmethod translate-from-foreign (value (type (eql 'my-boolean))) (not (zerop value)))
When a translate-to-foreign
method requires allocation of
foreign memory, you may specialize the free-translated-object
method to free the memory once the foreign object is no longer needed.
This is called automatically by CFFI when passing objects to
foreign functions.
A type translator does not necessarily need to convert the value. For
example, one could define a typedef for :pointer
that ensures,
in the translate-to-foreign
method, that the value is not a
null pointer, signalling an error if a null pointer is passed. This
will prevent some pointer errors when calling foreign functions that
cannot handle null pointers.
Please note: these methods are meant as extensible hooks
only, and you should not call them directly. Use
convert-to-foreign
, convert-from-foreign
and
free-converted-object
instead. These will take care of
following the typedef chain, for example, calling all the applicable
translators. They will also work for CFFI's built-in types, such
as enums.
See Defining new types, for a more involved tutorial example of type translators.