CFFI also provides a few useful types that aren't built-in C types.
: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 accept foreign pointers and pass them 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
: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))
:boolean type converts between a Lisp boolean and a C
boolean. It canonicalizes to base-type which is
(convert-to-foreign nil :boolean) => 0 (convert-to-foreign t :boolean) => 1 (convert-from-foreign 0 :boolean) => nil (convert-from-foreign 1 :boolean) => t
: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
(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