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: