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

Luís Oliveira luismbo at gmail.com
Sat Aug 27 21:56:36 UTC 2011


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?

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.


> 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.


> 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?

Cheers,

-- 
Luís Oliveira
http://r42.eu/~luis/




More information about the cffi-devel mailing list