CFFI also provides a few useful types that aren't built-in C types.
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 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
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))
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
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 funcall
s 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