27.11.2014 Views

CFFI User Manual - Common Lisp.net

CFFI User Manual - Common Lisp.net

CFFI User Manual - Common Lisp.net

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Chapter 6: Foreign Types 26<br />

6.5 Optimizing Type Translators<br />

Being based on generic functions, the type translation mechanism described above can add<br />

a bit of overhead. This is usually not significant, but we nevertheless provide a way of<br />

getting rid of the overhead for the cases where it matters.<br />

A good way to understand this issue is to look at the code generated by defcfun.<br />

Consider the following example using the previously defined my-string type:<br />

<strong>CFFI</strong>> (macroexpand-1 ’(defcfun foo my-string (x my-string)))<br />

;; (simplified, downcased, etc...)<br />

(defun foo (x)<br />

(multiple-value-bind (#:G2019 #:PARAM3149)<br />

(translate-to-foreign x #)<br />

(unwind-protect<br />

(translate-from-foreign<br />

(foreign-funcall "foo" :pointer #:G2019 :pointer)<br />

#)<br />

(free-translated-object #:G2019 #<br />

#:PARAM3149))))<br />

In order to get rid of those generic function calls, <strong>CFFI</strong> has another set of extensible generic<br />

functions that provide functionality similar to CL’s compiler macros: expand-to-foreigndyn,<br />

expand-to-foreign and expand-from-foreign. Here’s how one could define a myboolean<br />

with them:<br />

(define-foreign-type my-boolean-type ()<br />

()<br />

(:actual-type :int)<br />

(:simple-parser my-boolean))<br />

(defmethod expand-to-foreign (value (type my-boolean-type))<br />

‘(if ,value 1 0))<br />

(defmethod expand-from-foreign (value (type my-boolean-type))<br />

‘(not (zerop ,value)))<br />

And here’s what the macroexpansion of a function using this type would look like:<br />

<strong>CFFI</strong>> (macroexpand-1 ’(defcfun bar my-boolean (x my-boolean)))<br />

;; (simplified, downcased, etc...)<br />

(defun bar (x)<br />

(let ((#:g3182 (if x 1 0)))<br />

(not (zerop (foreign-funcall "bar" :int #:g3182 :int)))))<br />

No generic function overhead.<br />

Let’s go back to our my-string type. The expansion interface has no equivalent of freetranslated-object;<br />

you must instead define a method on expand-to-foreign-dyn, the<br />

third generic function in this interface. This is especially useful when you can allocate<br />

something much more efficiently if you know the object has dynamic extent, as is the case<br />

with function calls that don’t save the relevant allocated arguments.<br />

This exactly what we need for the my-string type:

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!