Problems with nested structs and the newer cffi

Liam Healy lnp at healy.washington.dc.us
Mon Apr 22 17:25:27 UTC 2013


Willem,

Thanks for the report.

My thinking is that with-foreign-slots is intended to expose the value (and
not the pointer), and therefore, expands to foreign-slot-value, so the
behavior you're seeing is correct. Your fix to your code is the correct way
to access the pointer. I think with-foreign-slots is provided as a
convenient shortcut to get all the values; since it doesn't do what you
need, you need to use the actual access form (foreign-slot-pointer in your
case).

For your second question: if the argument is actually a pointer to the
structure, :pointer is the right thing to use. Are you sure it is a pointer
argument? Check the .h file where it is defined.

Liam


On Sat, Apr 20, 2013 at 4:40 AM, Willem Rein Oudshoorn
<woudshoo at xs4all.nl>wrote:

> I am encountering some problems with trying to upgrade my old cffi code
> to the new version from quicklisp.
> If I use the old code, I get lots of warnings about my structs, that I
> should use either (:struct ...) or (:pointer (:struct ...))
>
> However whateer I try, I do not seem to get it to work, and I am
> starting to think there is some issue between me and the new cffi.
>
>
> The main issue is a nested struct definition like this:
>
> ```
> (defcstruct timeval
>   (time %time)
>   (offset :int))
>
> (defcstruct (git-signature)
>   (name :string)
>   (email :string)
>   (time (:struct timeval)))
> ```
>
> With type definitions
>
> ```
> (define-foreign-type time-type ()
>   nil
>   (:actual-type :int64)
>   (:simple-parser %time))
>
> (define-foreign-type git-signature-type ()
>   nil
>   (:actual-type :pointer)
>   (:simple-parser %git-signature))
> ```
>
> I encounter problems when I am trying to update the
> `translate-to-foreign` for the `git-signature-type`.
> The implementation boils down to:
>
> ```
> (defmethod translate-to-foreign ((value list) (type git-signature-type))
>   (let ((signature (foreign-alloc '(:struct git-signature))))
>     (with-foreign-slots ((name email time) signature (:struct
> git-signature))
>       (setf name (getf value :name (getenv "USER")))
>       (setf email (getf value :email (default-email)))
>       (with-foreign-slots ((time offset) time (:struct timeval))
>         (let ((time-to-set (getf value :time (local-time:now))))
>           (setf time time-to-set)
>           (setf offset (/ (local-time:timestamp-subtimezone
>                            time-to-set local-time:*default-timezone*)
>                           60)))))
>     signature)
> ```
>
> The problem is in the inner `with-foreign-slots ((time offset)...`.
>
> The error I get is:
>
> ; Evaluation aborted on #<TYPE-ERROR expected-type: SYSTEM-AREA-POINTER
>              datum: (CL-GIT::OFFSET 0 TIME
> @1970-01-01T01:00:03.000000+01:00)>.
>
>
> The reason is, as far as I can tell, that in the code:
>
>     (with-foreign-slots ((time offset) time (:struct timeval)) ...
>
> the value of `time` is already a plist (due to the outer
> with-foreign-slots), and the inner with-foreign-slots expects a pointer.
>
> So what is the best way of fixing this?  I can fix this by replacing
> the inner `with-foreign-slots` by
>
> ```
>       (with-foreign-slots ((time offset)
>                            (foreign-slot-pointer signature '(:struct
> git-signature) 'time)
>                            (:struct timeval))
> ```
> which seems a bit long.
>
>
> An additional question is, when to use (:struct ...) and when to use
> (:pointer (:struct ..)))
>
> I did expect that I needed to use (:pointer (:struct ..))
> in the toplevel `with-foreign-slots`, because the argument is actually
> a pointer to the struct.  But that did not work.
>
>
> As you can tell, I am a bit confused.
> Hope that someone can give some hints to clear my head.
>
> Kind regards,
> Wim Oudshoorn.
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/cffi-devel/attachments/20130422/8943f802/attachment.html>


More information about the cffi-devel mailing list