Next: , Previous: Built-In Types, Up: Foreign Types


5.2 Other Types

CFFI also provides a few useful types that aren't built-in C types.

— Foreign Type: :string

The :string type performs automatic conversion between Lisp and C strings. Note that, in the case of functions the converted C string will have dynamic extent (i.e. it will be automatically freed after the foreign function returns).

In addition to Lisp strings, this type will also convert Lisp arrays of element type (unsigned-byte 8) and will pass foreign pointers unmodified.

A method for free-translated-object is specialized for this type. So, for example, foreign strings allocated by this type and passed to a foreign function will be freed after the function returns.

  CFFI> (foreign-funcall "getenv" :string "SHELL" :string)
  => "/bin/bash"
   
  CFFI> (with-foreign-string (str "abcdef")
          (foreign-funcall "strlen" :string str :int))
  => 6
   
  CFFI> (let ((str (make-array 4 :element-type '(unsigned-byte 8)
                               :initial-element 65)))
          (foreign-funcall "strlen" :string str :int))
  => 4
— Foreign Type: :string+ptr

Like :string but returns a list with two values when convert from C to Lisp: a Lisp string and the C string's foreign pointer.

  CFFI> (foreign-funcall "getenv" :string "SHELL" :string+ptr)
  => ("/bin/bash" #.(SB-SYS:INT-SAP #XBFFFFC6F))
— Foreign Type: :boolean &optional (base-type :int)

The :boolean type converts between a Lisp boolean and a C boolean. It canonicalizes to base-type which is :int by default.

  (convert-to-foreign nil :boolean) => 0
  (convert-to-foreign t :boolean) => 1
  (convert-from-foreign 0 :boolean) => nil
  (convert-from-foreign 1 :boolean) => t
— Foreign Type: :wrapper base-type &key to-c from-c

The :wrapper type stores two symbols passed to the to-c and from-c arguments. When a value is being translated to or from C, this type funcalls the respective symbol.

:wrapper types will be typedefs for base-type and will inherit its translators, if any.

Here's an example of how the :boolean type could be defined in terms of :wrapper.

  (defun bool-c-to-lisp (value)
    (not (zerop value)))
   
  (defun bool-lisp-to-c (value)
    (if value 1 0))
   
  (defctype my-bool (:wrapper :int :from-c bool-c-to-lisp
                                   :to-c bool-lisp-to-c))
   
  (convert-to-foreign nil 'my-bool) => 0
  (convert-from-foreign 1 'my-bool) => t