[cffi-devel] defcstruct and array.
Hi, I`m experimenting with defcstruct. I tried the following: (*defcstruct* point (nr :int) (name :char :count 32) (coordinates :float :count 3)) which also works like: ... (coordinate1 :float) (coordinate2 :float) (coordinate3 :float) I`m getting the values like this: (*with-foreign-object* .... (*with-foreign-slots* ... nr by foreign-slot-value name by foreign-string-to-lisp but how do I read the array of floats with N dimensions into lisp? Maybe I am missing something obvious here. Thanks a lot.
mosi <amosat+python@gmail.com> writes:
(defcstruct point (nr :int) (name :char :count 32) (coordinates :float :count 3)) [...] but how do I read the array of floats with N dimensions into lisp?
The array functionality that CFFI currently exports is pretty low-level. Here's one way to do it: (with-foreign-slots ((coordinates) ptr point) ;; the COORDINATES slot is a pointer to the array, which ;; can be dereferenced through MEM-AREF. (loop for i below 3 collect (mem-aref coordinates :float i))) => (1.0 2.0 3.0) There has been some work on a higher-level interface, but it's currently unexported and unsupported (i.e. the interface may change in a backwards incompatible way). Here's an example: (with-foreign-slots ((coordinates) ptr point) ;; again, COORDINATES is a pointer. (cffi::foreign-array-to-lisp coordinates '(:array :float 3))) => #(1.0 2.0 3.0) We can make it a little more high-level (hacked this in just now and commited to the darcs repository, so if you want to try it, you need to darcs pull, since :ARRAY wasn't working properly for structs): (defcstruct another-point (nr :int) (name (:array :char 32)) (coordinates (:array :float 3))) (foreign-slot-value ptr 'another-point 'coordinates) => #(1.0 2.0 3.0) I suppose it'd be even better if DEFCSTRUCT defined some accessors. (IIRC, this has been suggested before.) Then you could simply use: (point-coordinates ptr) => #(1.0 2.0 3.0) Oh what the heck. :-) Hacked that in as well: (defcstruct (point :conc-name point-) (nr :int) (name (:array :char 32)) (coordinates (:array :float 3))) (with-foreign-object (p 'point) (setf (point-coordinates p) #(3.0 2.0 1.0)) (point-coordinates p)) => #(3.0 2.0 1.0) I hope that's useful, but keep in mind that this functionality is undocumented, unexported and unsupported. :-) Suggestions for some name better than :CONC-NAME are welcome! -- Luís Oliveira http://student.dei.uc.pt/~lmoliv/
participants (2)
-
Luis Oliveira
-
mosi