Liam Healy | 18 Feb 18:53 2012

Re: [cffi] FSBV (#2)

The new syntax is as follows.  If you want the structure itself, use (:struct foo).  If you want a pointer to it, use (:pointer (:struct foo)).   The latter should be identical to the old style bare struct specification, except for the annoying deprecation warning, of course.

The issues I can identify, with their resolutions:

1) Using mem-aref with the (:pointer (:struct ...)) spec gives the wrong pointer.

I have fixed an error which should now return the correct pointer for an offset of 0.  For an offset of 1, it returns the base pointer +8 bytes, which is not what the old style gives (+ 4 bytes), but it seems to me correct, as I understand the index to refer to the number of whole structures.   Pull ee90bfd517 and try.

2) The plist form representing the structure is not desirable.

You can have any CL representation of the structure you like; you need to define a method cffi:translate-from-foreign for your type class.  You are getting the default, a plist translation, because no such method is defined.   See for example how I translate complex numbers to CL complex numbers.  You can even return a pointer if you want, but this probably isn't the specification to use if you want the pointer.

On Mon, Feb 13, 2012 at 10:22 AM, Ryan Pavlik <reply+i-1614209-ba246666762196459413560690eb7d3a39c7c7ee-838019 <at>> wrote:
I've pulled the latest and it appears the semantics have changed for mem-aref, but there is still no way to get the old behavior.  Here is a complete example, though it doesn't use the test system definitions because actual foreign calls and definitions aren't really the problem:

(asdf:load-system :cffi)

(cffi:defcstruct my-struct
 (x :short)
 (y :short))

(defun test-old-ref ()
 (declare (notinline cffi:mem-ref cffi:mem-aref))
 (cffi:with-foreign-object (ptr '(:struct my-struct) 2)
   (format t "~&Old-ref style:~%ptr : ~A~%aref: ~A~%"
           ptr (cffi:mem-aref ptr 'my-struct 1))))

(defun test-new-ref ()
 (cffi:with-foreign-object (ptr '(:struct my-struct) 2)
   (format t "~&New-ref style:~%ptr : ~A~%aref: ~A~%"
          (cffi:mem-aref ptr '(:struct my-struct) 1))))

(defun test-new-ptr-ref ()
 (cffi:with-foreign-object (ptr '(:struct my-struct) 2)
   (format t "~&New-ref with :pointer style:~%ptr : ~A~%aref: ~A~%"
          (cffi:mem-aref ptr '(:pointer (:struct my-struct)) 1))))


The output I get, sans style-warnings about bare structs:

Old-ref style:
New-ref style:
aref: (Y 0 X 0)
New-ref with :pointer style:
aref: #.(SB-SYS:INT-SAP #X00000000)

Note that in the first example, with the original semantics, if you mem-aref a pointer to an array of `my-struct`, you get a pointer to the array element.  In the new style, with `(:struct my-struct)`, you get the values parsed into a list, which is not particularly useful; it conses, and you almost certainly have to re-parse a possibly long list for a single element.  In the new style with `:pointer`, it appears to dereference the Nth element in an *array of pointers to my-struct*, which is not at all what we want.

The latter differs from the behavior before I updated, which seemed to return a *pointer* to the Nth element in an array-of-pointers.  None of the above are like the old behavior.

Reply to this email directly or view it on GitHub:

cffi-devel mailing list
cffi-devel <at>