[cffi-devel] Converting foreign structures with CFFI generic functions

Liam Healy lnp at healy.washington.dc.us
Sun Aug 28 04:42:40 UTC 2011


On Sat, Aug 27, 2011 at 5:56 PM, Luís Oliveira <luismbo at gmail.com> wrote:

> On Sat, Aug 27, 2011 at 10:11 PM, Liam Healy <lnp at healy.washington.dc.us>
> wrote:
> > So you're suggesting retaining the :constructor and :deconstructor
> arguments
> > to defcstruct?    It seems like a custom translate-*-foreign may be more
> > compatible with existing CFFI, though I guess a compatibility expansion
> > might be convenient.
>
> No, that's not what I meant. Let's take your COMPLEX example. That
> should make things clearer.
>
> (defcstruct (complex :class complex-type)
>  (real :double)
>  (imag :double))
>
> (defmethod translate-to-foreign ((value complex) (type complex-type))
>  (let ((p (foreign-alloc 'complex)))
>    (with-foreign-slots ((real imag) p 'complex)
>      (setf real (realpart value)
>            imag (imagpart value)))
>    (values p t)) ; second value is passed to FREE-TRANSLATED-OBJECT
>
> (defmethod free-translated-object (value (p complex-type) freep)
>  (when freep
>    (foreign-free value)))
>
> (defmethod translate-from-foreign (value (type complex-type))
>  ...)
>
> (defcfun (complex-conjugate "gsl_complex_conjugate") complex
>  (c (:by-value complex)) ; or something like that.
>
> ;; we can then call it like this:
>
> (complex-conjugate #c(3.0d0 4.0d0))
> #C(3.0 -4.0)
>
> ;; what I was proposing is that one could /also/ call it like this:
>
> (with-foreign-object (p 'complex)
>  (with-foreign-slots ((real imag) p 'complex)
>    (setf real 3.0 imag -4.0))
>  (complex-conjugate p))
>
>
> In summary, we're always dealing with struct pointers, but the
> function declaration will determine whether that struct will be passed
> by value or not. Does that make sense?
>

Yes.  I'm not (yet) concerned about the function declaration or the libffi
call, because my confusion was about the conversion structure and how it
might apply to structures, even before any foreign functions are called.


>
> My follow-up question was: is this too subtle? Should we make this
> more explicit? E.g.:
>
> (with-foreign-object (p 'complex)
>  (with-foreign-slots ((real imag) p 'complex)
>    (setf real 3.0 imag -4.0))
>  (complex-conjugate (struct-pointer-value p)))
>
> Doesn't look too pretty.
>

No, I don't like this either.


>
>
> > For a default conversion assuming a structure on the lisp side, I'm not
> sure
> > how to iterate over the structure.  Maybe MOP has something?  I do have
> > iterate-foreign-structure.   If I assume a list or vector on the lisp
> side,
> > then I could iterate through it.
>
> If we add such a feature, I guess the Lisp structure (or class) should
> be defined by defcstruct itself.
>

Good point.

>
>
> > If I define a specializer for a particular cstruct, what should the class
> > be?  This looks like a type name, not the actual object that's passed as
> the
> > second argument 'type, so I presume it should be an eql specializer on
> the
> > name, but I admit I'm getting confused by this.  In any case I think the
> > :class option to defcstruct won't always work because it does a defclass,
> I
> > need something like :existing-class that would just do a find-class.
>
> Hopefully my example with COMPLEX-TYPE illustrates how that works. The
> type argument gets an instance of COMPLEX-TYPE, which is the result of
> (parse-type 'complex). Was it clear?
>

Yes, thanks.  The subclassing of type names was confusing me.  The example
makes it clear.  I think I will define a macro to make the creation of the
translate-*-foreign and free-translated-object methods a little bit easier.

Liam


> Cheers,
>
> --
> Luís Oliveira
> http://r42.eu/~luis/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/cffi-devel/attachments/20110828/51d7dbdc/attachment.html>


More information about the cffi-devel mailing list