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

6.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 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.