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!