On Sat, Aug 27, 2011 at 5:56 PM, Luís Oliveira luismbo@gmail.com wrote:
On Sat, Aug 27, 2011 at 10:11 PM, Liam Healy lnp@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/