[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