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 numbershttp://repo.or.cz/w/antik.git/blob/1ee407c69525b84b441f8cf7b48ac590e78bd635:/foreign-array/complex-types.lisp#l50to 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@reply.github.com
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~%" ptr (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~%" ptr (cffi:mem-aref ptr '(:pointer (:struct my-struct)) 1)))) (progn (test-old-ref) (test-new-ref) (test-new-ptr-ref))
The output I get, sans style-warnings about bare structs:
Old-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFCFFF0) aref: #.(SB-SYS:INT-SAP #X7FFFEEFCFFF4) New-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFCFFF0) aref: (Y 0 X 0) New-ref with :pointer style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFCFFF0) 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: https://github.com/cffi/cffi/pull/2#issuecomment-3941718
This looks wrong to me -- a pointer is not an aggregate type. Also, I think your test-new-ptr-ref and test-generic-ptr-ref tests are bogus because the type in mem-aref doesn't match the type of ptr.
Have you tried it with a struct containing 20 bytes? Testing it with an array of two 4 byte structs leads to confusion about the size of a pointer v.s. the size of one struct v.s. the size of the array.
In fact, I don't understand what mem-aref is supposed to do for an aggregate type. Making it return a pointer to the first byte of the aggregate is inconsistent with how it treats other types and IMHO leads to the current confusion.
__Martin
On Sat, 18 Feb 2012 12:53:17 -0500, Liam Healy said:
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:
- 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.
- 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 numbershttp://repo.or.cz/w/antik.git/blob/1ee407c69525b84b441f8cf7b48ac590e78bd635:/foreign-array/complex-types.lisp#l50to 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@reply.github.com
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~%" ptr (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~%" ptr (cffi:mem-aref ptr '(:pointer (:struct my-struct)) 1)))) (progn (test-old-ref) (test-new-ref) (test-new-ptr-ref))
The output I get, sans style-warnings about bare structs:
Old-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFCFFF0) aref: #.(SB-SYS:INT-SAP #X7FFFEEFCFFF4) New-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFCFFF0) aref: (Y 0 X 0) New-ref with :pointer style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFCFFF0) 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: https://github.com/cffi/cffi/pull/2#issuecomment-3941718
I'm not sure how to address Ryan's case (what I identified as (1)). I am (effectively) scrapping the changes I have made by redefining defmethod aggregatep ((type foreign-pointer-type)) to give nil, because I found having it T seriously broke GSLL. I acknowledge your points and Ryan's in his last email but I don't understand pointers and aggregates and structures in C and how they should map to CL enough to understand what to do. Any thoughts appreciated (Luis? anyone?).
Liam
On Mon, Feb 20, 2012 at 10:38 AM, Martin Simmons martin@lispworks.comwrote:
This looks wrong to me -- a pointer is not an aggregate type. Also, I think your test-new-ptr-ref and test-generic-ptr-ref tests are bogus because the type in mem-aref doesn't match the type of ptr.
Have you tried it with a struct containing 20 bytes? Testing it with an array of two 4 byte structs leads to confusion about the size of a pointer v.s. the size of one struct v.s. the size of the array.
In fact, I don't understand what mem-aref is supposed to do for an aggregate type. Making it return a pointer to the first byte of the aggregate is inconsistent with how it treats other types and IMHO leads to the current confusion.
__Martin
On Sat, 18 Feb 2012 12:53:17 -0500, Liam Healy said:
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:
- 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.
- 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<
http://repo.or.cz/w/antik.git/blob/1ee407c69525b84b441f8cf7b48ac590e78bd635:...
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@reply.github.com
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~%" ptr (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~%" ptr (cffi:mem-aref ptr '(:pointer (:struct my-struct)) 1)))) (progn (test-old-ref) (test-new-ref) (test-new-ptr-ref))
The output I get, sans style-warnings about bare structs:
Old-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFCFFF0) aref: #.(SB-SYS:INT-SAP #X7FFFEEFCFFF4) New-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFCFFF0) aref: (Y 0 X 0) New-ref with :pointer style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFCFFF0) 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: https://github.com/cffi/cffi/pull/2#issuecomment-3941718
cffi-devel mailing list cffi-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/cffi-devel