Type translators are used to automatically convert Lisp values to or
from foreign values. For example, using type translators, one can
take the my-string
type defined in the previous section and
specify that it should:
In order to tell CFFI how to automatically convert Lisp values to
foreign values, define a specialized method for the
translate-to-foreign
generic function:
;;; Define a method that converts Lisp strings to C strings. (defmethod translate-to-foreign (string (type my-string-type)) (foreign-string-alloc string :encoding (string-type-encoding type)))
From now on, whenever an object is passed as a my-string
to a
foreign function, this method will be invoked to convert the Lisp
value. To perform the inverse operation, which is needed for functions
that return a my-string
, specialize the
translate-from-foreign
generic function in the same manner:
;;; Define a method that converts C strings to Lisp strings. (defmethod translate-from-foreign (pointer (type my-string-type)) (foreign-string-to-lisp pointer :encoding (string-type-encoding type)))
When a translate-to-foreign
method requires allocation of
foreign memory, you must also define a free-translated-object
method to free the memory once the foreign object is no longer needed,
otherwise you'll be faced with memory leaks. This generic function is
called automatically by CFFI when passing objects to foreign
functions. Let's do that:
;;; Free strings allocated by translate-to-foreign. (defmethod free-translated-object (pointer (type my-string-type) param) (declare (ignore param)) (foreign-string-free pointer))
In this specific example, we don't need the param argument, so we ignore it. See free-translated-object, for an explanation of its purpose and how you can use it.
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
would 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.
See Defining new types, for another example of type translators.