Next: , Previous: Defining Typedefs, Up: Foreign Types


5.4 Foreign Type Translators

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.