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 <wouds...@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. > > >