[cffi-devel] Type translators

Luis Oliveira luismbo at gmail.com
Thu Aug 4 02:49:59 UTC 2005


Hello,

I'm reworking the type translator interface. The idea is to simplify 
and allow for more flexibility. I'll start with some examples:

This is how the boolean type would be defined with the current 
interface:

   (defctype boolean :int)

   (define-type-translator boolean :in (arg result-var)
     "Type translator to convert t/nil to a C boolean."
     (values `(if ,arg 1 0) nil))

   (define-type-translator boolean :result (arg result-var)
     "Type translator to convert C booleans to t/nil."
     (values `(if (zerop ,arg) nil t)))

First thing I'm changing is :in/:return, the names don't make sense 
when we think about callbacks, the :return translation is applied for 
the arguments and :in for the callback's return value. So I picked 
:to-c and :from-c. Can someone suggest better names?

And this is how my interface would look like:

   (define-type-translation (boolean :int)
     "Converting between C ints and Lisp booleans."
     :to-c (if &value 1 0)
     :from-c (if (zerop &value) nil t))

It takes care of the defctype unless the first arg isn't a list. If it 
were just 'boolean' defctype woudn't be used (eg. when defining a 
type-translating for a struct type). Hmm, is this extra syntax re 
defctype overkill?

Also it sets up &value with symbol-macrolet.


Another example, the string type. Before:

   (defctype string :pointer)

   (define-type-translator string :to-c (arg result-var)
     "Type translator for converting Lisp strings to C string."
     (values `(foreign-string-alloc ,arg) `((foreign-string-free 
,result-var))))

   (define-type-translator string :from-c (arg result-var)
     "Type translator for C string values."
     `(foreign-string-to-lisp ,arg))

After:

   (define-type-translation (string :pointer)
     "Converting between C and Lisp strings."
     :in (let ((&var (foreign-string-alloc &value)))
           (unwind-protect
                (&body)
             (foreign-string-free &var)))
     :to-c (foreign-string-alloc &value)
     :from-c (foreign-string-to-lisp &value))

Here we have an extra translation :in, used when we are actually 
passing something to a foreign function (the :to-c translation is used, 
in case :in is undefined). Here we have to explicitly write the 
unwind-protect, I think the translation becomes more readable this way. 
:in also sets up a few more (symbol-)macros, &var and &body whose 
meaning should be obvious.

Getting to decide where &body goes (ie. not having to be restricted to 
a unwind-protect form as before) gives us the ability to do this:

   (define-type-translation (string :pointer)
     "Converting between C and Lisp strings."
     :in (with-foreign-string (&var &value)
           (&body))
     :to-c
     (foreign-string-alloc &value)
     :from-c
     (foreign-string-to-lisp &value))


This way the string is stack allocated (if the lisp supports this).


In this last example, I indented the code in a different way, I'm not 
yet happy with the syntax, any comments or suggestions regarding 
syntax, naming, etc.. will be most appreciated.

Also, the :to-c/:from-c translations, unlike :in, don't have access to 
&body as I couldn't think of a situation where this would be necessary. 
Am I missing something?

-- 
Luís Oliveira
http://student.dei.uc.pt/~lmoliv/
Equipa Portuguesa do Translation Project
http://www2.iro.umontreal.ca/~pinard/po/registry.cgi?team=pt



More information about the cffi-devel mailing list