[cffi-devel] Re: Type translators
James Bielman
jamesjb at jamesjb.com
Thu Aug 4 03:57:03 UTC 2005
Luis Oliveira <luismbo at gmail.com> writes:
> 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?
I think this is a good improvement. I always knew the type translator
syntax was too complicated but never got around to simplifying it.
As for the DEFCTYPE syntax, how about another keyword argument:
(define-type-translation boolean
"doc"
:c-type :int
:to-c ...
:from-c ...)
> Also it sets up &value with symbol-macrolet.
I must admit I'm not wild about using &symbols as placeholders inside
these expansions, as I think that's a naming convention best left
unique to lambda list keywords.
Here are some alternative syntaxes (besides just renaming the symbol
macros), I'm sure there are more:
;; Use special variables instead of symbol macros:
:in (let ((*var* (foreign-string-alloc *value*)))
(unwind-protect
(progn *body*)
(foreign-string-free *var*)))
;; Use MACROLET, sort of like CALL-NEXT-METHOD:
:in (let (((var) (foreign-string-alloc (value))))
(unwind-protect
(progn (body))
(foreign-string-free (var))))
;; IMO the cleanest, but also verbose, using a function
;; that returns the form using backquote:
:in (lambda (var value body)
`(let ((,var (foreign-string-alloc ,value)))
(unwind-protect
(progn , at body)
(foreign-string-free ,var))))
> 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).
Yes, this was one of my big complaints about my current design. :-)
> 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.
:IN might be better named something that makes it clear that it is
fulfilling a similar purpose to :TO-C except it is used only in the
special circumstance of passing arguments to a function. Maybe
:TO-C-ARG or something...
James
More information about the cffi-devel
mailing list