From: Sam S. <sd...@gn...> - 2010-08-05 15:25:40
|
Hi, Joe...@t-... wrote: > > Sam Steingold asked: >> why does this work: >> (def-call-out getloadavg (:return-type int) >> (:arguments (loadavg (c-ptr (c-array double-float 3)) :out :alloca) >> i.e., prints #(2.02d0 1.73d0 1.4d0) >> and returns (3 (SIMPLE-ARRAY DOUBLE-FLOAT (3))) >> while this does not: >> (let ((v (make-array 3 :element-type 'double-float))) >> (def-call-out getloadavg (:return-type int) >> (:library :default) (:language :stdc) >> (:arguments (loadavg (c-array double-float 3)) >> (nelem int))) >> (list (getloadavg v 3) >> (type-of (show v)))) >> i.e., prints #(0.0d0 0.0d0 0.0d0) >> and returns (0 (SIMPLE-ARRAY DOUBLE-FLOAT (3))) > > In CLISP's FFI, an array is never a pointer. Your second definition is wrong. oh yeah - it will want to _COPY_ the vector... > It's surprising that it was accepted because I seem to remember > that there was a check precisely to protect against this common error. > Only (C-PTR (C-ARRAY ...)) is correct. > (Is the check only with :OUT?) yes. > Furthermore, why do you expect a foreign function to write into the > Lisp array without :IN-OUT declaration? That would completely (let ((v (make-array 3 :element-type 'double-float))) (def-call-out getloadavg (:return-type int) (:library :default) (:language :stdc) (:arguments (loadavg (c-ptr (c-array double-float 3)) :in-out) (nelem int))) (list (getloadavg v 3) (type-of (print v)))) ==> #(0.0d0 0.0d0 0.0d0) (3 (SIMPLE-ARRAY DOUBLE-FLOAT (3))) i.e., the array is not filled with the return values. > change the semantics of the FFI. I think you SHOULD NOT do that > (but then, perhaps other implementations do this and find it cool -- the > full thing would require a protocol for pinning objects in memory as > well as declaring the extend of objects because the function call > declaration does not say anything about the lifetime of the address > that was revealed to C). that's a good point. passing the actual underlying array data to the foreign library in the MT world would require pinning the array. > BTW, do you copy the foreign array to a Lisp array on return from the > foreign function? That would be for sure inefficient. OTOH, if you pass > the address of a specialised Lisp array for double floats, you'll get different > results depending on the Lisp parameter type. > > (ff lisp-double-float-array #|as :in-out|#) > Case a: double-float-array's type is as the name implies pin the lisp object and pass the data vector to the C world. > Case b: a general purpose (array-element-type T) array signal a type error. this is what I think _should_ be done. obviously, this is not what actually _IS_ done. I guess we need to extend the clisp FFI to accept this kind of arguments: (argname lisp-data) which would pin the lisp object and pass a void* pointer to the data vector of lisp object which should be a simple vector (integer or float). WDYT? Bruno? Thanks. Sam. |