For dereferencing a struct you need to use the :copy-foreign-object keyword.. As the doc for FLI:DEREFERENCE says, 'An error is signaled if value is an aggregate type and copy-foreign-object is not set accordingly.' Setting it to T or NIL should work (default is ERROR).
Subject: Re: foreign function returning pointer to struct
From: and-ly@online.no
Date: Mon, 11 Jun 2012 19:39:51 +0200
CC: lisp-hug@lispworks.com
To: massung@gmail.com
Thanks for the reply.
It's not possible to dereference such a pointer
CL-USER 91 > (fli:dereference *ptr*)
Error: Attempted to dereference a pointer to aggregate type (:STRUCT MY-STRUCT).
CL-USER 93 > *ptr*
#<Pointer to type (:STRUCT MY-STRUCT) = #x00148400>
Reading the docs further it appears that I should omit the :pointer in the :result type
(fli:define-foreign-function (a-test "a_test" :source)
()
:result-type my-struct
:module "/Users/stinky/Work/ML/libtest.so")
And call an allocated foreign object for the :result-pointer key
CL-USER 94 > (setf *x* (fli:allocate-foreign-object :type 'my-struct))
#<Pointer to type (:STRUCT MY-STRUCT) = #x003A3B20>
CL-USER 95 > (a-test :result-pointer *x*)
#<Pointer to type (:STRUCT MY-STRUCT) = #x003A3B20>
But this results in completely rubbish struct field values
CL-USER 101 > (fli:foreign-slot-value *x* 'a)
1581056
CL-USER 102 > (fli:foreign-slot-value *x* 'b)
0
I haven't found any examples of this in the docs or elsewhere so hopefully someone who knows how this works can help me out :)
Kind regards
André Lynum
On Jun 11, 2012, at 5:36 PM, Jeffrey Massung wrote:
On Jun 11, 2012, at 7:59 AM, André Lynum wrote:
When calling my function and accessing the struct fields I get garbage in the second field
CL-USER 21 > (setf *ptr* (a-test))
#<Pointer to type (:STRUCT MY-STRUCT) = #x0015C7D0>
CL-USER 22 > (fli:foreign-slot-value *ptr* 'b)
1383793
CL-USER 23 > (fli:foreign-slot-value *ptr* 'a)
13
Andre,
I don't have time at the moment to put together my own test, but the above behavior looks correct. LispWorks doesn't have the C equivalent of the -> operator, only the . operator. Accessing slow 'a only appears to work because it's at byte offset 0 from the pointer address. You'll need to dereference the pointer first (to get a my-struct) and then access the slots in it.
(let ((s (dereference *ptr*)))
(values
(foreign-slot-value s 'b)
(foreign-slot-value s 'a)))
=> 14 13
Again, the above isn't tested, but I'm pretty confident. ;-)
- jeff