You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Chapter 6: Foreign Types 24<br />
:boolean &optional (base-type :int)<br />
[Foreign Type]<br />
The :boolean type converts between a <strong>Lisp</strong> boolean and a C boolean. It canonicalizes<br />
to base-type which is :int by default.<br />
(convert-to-foreign nil :boolean) ⇒ 0<br />
(convert-to-foreign t :boolean) ⇒ 1<br />
(convert-from-foreign 0 :boolean) ⇒ nil<br />
(convert-from-foreign 1 :boolean) ⇒ t<br />
:wrapper base-type &key to-c from-c<br />
[Foreign Type]<br />
The :wrapper type stores two symbols passed to the to-c and from-c arguments. When<br />
a value is being translated to or from C, this type funcalls the respective symbol.<br />
:wrapper types will be typedefs for base-type and will inherit its translators, if any.<br />
Here’s an example of how the :boolean type could be defined in terms of :wrapper.<br />
(defun bool-c-to-lisp (value)<br />
(not (zerop value)))<br />
(defun bool-lisp-to-c (value)<br />
(if value 1 0))<br />
(defctype my-bool (:wrapper :int :from-c bool-c-to-lisp<br />
:to-c bool-lisp-to-c))<br />
(convert-to-foreign nil ’my-bool) ⇒ 0<br />
(convert-from-foreign 1 ’my-bool) ⇒ t<br />
6.3 Defining Foreign Types<br />
You can define simple C-like typedefs through the defctype macro. Defining a typedef is<br />
as simple as giving defctype a new name and the name of the type to be wrapped.<br />
;;; Define MY-INT as an alias for the built-in type :INT.<br />
(defctype my-int :int)<br />
With this type definition, one can, for instance, declare arguments to foreign functions<br />
as having the type my-int, and they will be passed as integers.<br />
More complex types<br />
<strong>CFFI</strong> offers another way to define types through define-foreign-type, a thin wrapper<br />
macro around defclass. As an example, let’s go through the steps needed to define a<br />
(my-string &key encoding) type. First, we need to define our type class:<br />
(define-foreign-type my-string-type ()<br />
((encoding :reader string-type-encoding :initarg :encoding))<br />
(:actual-type :pointer))<br />
The :actual-type class option tells <strong>CFFI</strong> that this type will ultimately be passed to and<br />
received from foreign code as a :pointer. Now you need to tell <strong>CFFI</strong> how to parse a type<br />
specification such as (my-string :encoding :utf8) into an instance of my-string-type.<br />
We do that with define-parse-method: