I think Martin is right, so I have implemented mem-aptr and updated the manual. Here are Ryan's examples:
(cffi:defcstruct rp-struct (x :short) (y :short))
(defun test-old-ref (&optional (count 0)) (declare (notinline cffi:mem-ref cffi:mem-aref)) (cffi:with-foreign-object (ptr '(:struct rp-struct) 2) (format t "~&Old-ref style:~%ptr : ~A~%aref: ~A~%" ptr (cffi:mem-aref ptr 'rp-struct count))))
(defun test-new-ref (&optional (count 0)) (cffi:with-foreign-object (ptr '(:struct rp-struct) 2) (format t "~&New-ref style:~%ptr : ~A~%aref: ~A~%" ptr (cffi:mem-aptr ptr '(:struct rp-struct) count))))
CFFI(14): (test-old-ref) STYLE-WARNING: bare references to struct types are deprecated. Please use (:STRUCT RP-STRUCT) instead. STYLE-WARNING: bare references to struct types are deprecated. Please use (:STRUCT RP-STRUCT) instead. STYLE-WARNING: bare references to struct types are deprecated. Please use (:POINTER (:STRUCT RP-STRUCT)) instead.
Old-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFF6E97FF0) aref: #.(SB-SYS:INT-SAP #X7FFFF6E97FF0) NIL CFFI(15): (test-new-ref)
New-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFF6E97FF0) aref: #.(SB-SYS:INT-SAP #X7FFFF6E97FF0) NIL CFFI(16): (test-old-ref 1) STYLE-WARNING: bare references to struct types are deprecated. Please use (:STRUCT RP-STRUCT) instead. STYLE-WARNING: bare references to struct types are deprecated. Please use (:STRUCT RP-STRUCT) instead. STYLE-WARNING: bare references to struct types are deprecated. Please use (:POINTER (:STRUCT RP-STRUCT)) instead.
Old-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFF6E97FF0) aref: #.(SB-SYS:INT-SAP #X7FFFF6E97FF4) NIL CFFI(17): (test-new-ref 1)
New-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFF6E97FF0) aref: #.(SB-SYS:INT-SAP #X7FFFF6E97FF4) NIL
This looks right to me. I made a new branch libffi; the old branch fsbv will be abandoned. Note that generation of a pointer from mem-aref for structures is only supported when using the deprecated "bare" structures form, for compatibility reasons; otherwise you should use mem-aptr. Please checkout this branch and see if it works correctly for you and looks right. I agree as Martin said the other examples are incorrectly written, so I'm not bothering with them.
Head: 0fec6ff839 - Update manual to include mem-aptr
Liam
On Fri, Feb 24, 2012 at 7:34 AM, Martin Simmons martin@lispworks.comwrote:
To answer Ryan's point, I think there should be a different function to get a pointer to an element of an array, called something like mem-aptr. It should work for all element types, not just aggregates.
That allows mem-aref to have "value" semantics for all types. For aggregates, converting to a plist is one possible way to representing it.
-- Martin Simmons LispWorks Ltd http://www.lispworks.com/
On Mon, 20 Feb 2012 12:12:44 -0500, Liam Healy said:
Ryan -
I am forwarding this to CFFI-devel and Martin directly (though I'm pretty sure he's subscribed to cffi-devel). Can you please send future messages to cffi-devel? I'm not sure many people read the github mailing list;
this
issue should get wider visibility. Thanks.
Liam
On Mon, Feb 20, 2012 at 12:02 PM, Ryan Pavlik <
reply+i-1614209-ba246666762196459413560690eb7d3a39c7c7ee-838019@reply.github.com
wrote:
I'm not sure what you mean. It doesn't really matter that a pointer is aggregate or not. The goal is to get at the Nth member of an array-of-something. In the case of scalar C types, you're getting the value; in the case of structs it's far more useful to get a pointer, because you probably only want a single value out of the struct, or to **put a value into the struct**. (The `setf` form works for scalars
in the
latter case, but not for "member-of-struct-of-index-N"... you most
likely
want the pointer in these cases.)
It also occurred to me after posting that there is no difference
between
`(mem-aref ptr '(:pointer (:struct foo)) N)` and just simply
`(mem-aref ptr
:pointer N)` ... both return a pointer value as if `ptr` is a `void *ptr[k]`.
A struct of more bytes works the same way:
(cffi:defcstruct my-struct (x :long) (y :long) (x :long) (t :long)) ... Old-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFC7FB8) aref: #.(SB-SYS:INT-SAP #X7FFFEEFC7FD8) New-ref style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFC7FB8) aref: (T 0 Y 0 X 0) New-ref with :pointer style: ptr : #.(SB-SYS:INT-SAP #X7FFFEEFC7FB8) aref: #.(SB-SYS:INT-SAP #X00000000)
Note that on my system, a pointer is 8 bytes, not 4. This is why I initially found the problem, when trying to access an array of points defined by 2 short; each member is 4 bytes, and it was giving offsets
to
`sizeof(void*)`.
Reply to this email directly or view it on GitHub: https://github.com/cffi/cffi/pull/2#issuecomment-4057418