[cffi-devel] Type translators

Rayiner Hashem rayiner at gmail.com
Thu Aug 4 04:09:52 UTC 2005


Sounds interesting. I like the idea of putting everything into one
declaration instead of having two as before. I think "to-c" and
"from-c" are fine names. A cuter name would just make it easier to get
the two directions mixed up, IMHO.

I've got one question and one suggestion. Excuse me if they're dumb,
because I'm not too up-to-date on the workings of C-FFI.

1) How does the translator interface express more complex C values?
Say, I want the "to-c" clause to send a struct to the C code? Can I
just return an object allocated by foreign-object-alloc?

2) Is there any way to make translations optional, and only invoke
them on particular arguments in a given function declaration?

I'm also thinking about one other thing. Say I'm wrapping this function:

void cairo_line_to(cairo_t* cr, double x, double y);

I'd like the Lisp declaration to be as if the function was:

(defun cairo-line-to (cr pt) ...) where 't' is a 'point' structure or
maybe just a (x . y) cons cell. Would it be reasonable to include that
kind of translation in the FFI, or would it be more prudent to put
that in a higher layer?

Sincerely,
    Rayiner Hashem

On 8/3/05, Luis Oliveira <luismbo at gmail.com> wrote:
> 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
> _______________________________________________
> cffi-devel mailing list
> cffi-devel at common-lisp.net
> http://common-lisp.net/cgi-bin/mailman/listinfo/cffi-devel
>



More information about the cffi-devel mailing list