Hi all:
I do habe C structs lile these:
struct a_struct { int a; };
struct b_struct { int b; struct a_struct a; };
How would I model b_struct using defcstruct ?
Thx for any hints!
Regards, Frank
Frank Goenninger fgoenninger@prion.de writes:
I do habe C structs lile these:
struct a_struct { int a; };
struct b_struct { int b; struct a_struct a; };
How would I model b_struct using defcstruct ?
It looks like what you would think:
(defcstruct a-struct (a :int))
(defcstruct b-struct (b :int) (a a-struct))
It's confusing, because CFFI tries to avoid passing aggregate C objects by value. For instance, if you declare a function argument as having type A-STRUCT, you get a pointer instead, because you can't pass structures by value in CFFI.
But in a structure, you do need to able to include a structure, not just a pointer to it. So the obvious thing does what you want.
In retrospect, the foreign type A-STRUCT should probably always mean the structure itself by value, and declaring a function like:
(defcfun struct-by-value :void (a a-struct))
should probably just be an error, instead of the DWIM-ish behavior of canonicalizing A-STRUCT to :POINTER. (And someday the Lisp implementations may be extended to pass structures by value, and we will want to support that.)
Ideally, :POINTER should probably become a parameterized type, so that function would instead be:
(defcfun struct-by-pointer :void (a (:pointer a-struct))
which will help us down the road when we implement optional pointer type checking.
Any thoughts? This would be a pretty incompatible change, but it's probably better to fix it soon then let more code get written that takes advantage of this (IMHO) misfeature.
James
James Bielman jamesjb@jamesjb.com writes:
Frank Goenninger fgoenninger@prion.de writes:
I do habe C structs lile these:
struct a_struct { int a; };
struct b_struct { int b; struct a_struct a; };
How would I model b_struct using defcstruct ?
It looks like what you would think:
(defcstruct a-struct (a :int))
(defcstruct b-struct (b :int) (a a-struct))
I should add that another potentially confusing thing here is when you access the A slot of a B-STRUCT, you get back a pointer to it, instead of the A-STRUCT by value. For example:
(foreign-slot-value b 'b-struct 'b) -> 100 ; an int (foreign-slot-value b 'b-struct 'a) -> #<pointer ...> ; a pointer
Probably this DWIM-ish behavior was also a mistake, and you should use FOREIGN-SLOT-POINTER to access the structure instead (which does work now):
(foreign-slot-value b 'b-struct 'a) -> error! (foreign-slot-pointer b 'b-struct 'a) -> #<pointer ...>
James
Am 07.05.2006 um 00:50 schrieb James Bielman:
Frank Goenninger fgoenninger@prion.de writes:
I do habe C structs lile these:
struct a_struct { int a; };
struct b_struct { int b; struct a_struct a; };
How would I model b_struct using defcstruct ?
It looks like what you would think:
(defcstruct a-struct (a :int))
(defcstruct b-struct (b :int) (a a-struct))
Hmmm - didn't think of this because I seem to have read something along the lines of what you say:
It's confusing, because CFFI tries to avoid passing aggregate C objects by value. For instance, if you declare a function argument as having type A-STRUCT, you get a pointer instead, because you can't pass structures by value in CFFI.
But in a structure, you do need to able to include a structure, not just a pointer to it. So the obvious thing does what you want.
Anyway: Thanks!
In retrospect, the foreign type A-STRUCT should probably always mean the structure itself by value, and declaring a function like:
(defcfun struct-by-value :void (a a-struct))
should probably just be an error, instead of the DWIM-ish behavior of canonicalizing A-STRUCT to :POINTER.
It certainly would be more puristic and IMHO clean.
(And someday the Lisp implementations may be extended to pass structures by value, and we will want to support that.)
Ideally, :POINTER should probably become a parameterized type, so that function would instead be:
(defcfun struct-by-pointer :void (a (:pointer a-struct))
which will help us down the road when we implement optional pointer type checking.
Which I'd prefer also ! Let's you not only do type checking but is what I need most: As close to C as it can get. I'd have some translate-from/to-foreign functions specializing on the pointer type rather than defining a new type and dispatching on that.
Any thoughts? This would be a pretty incompatible change, but it's probably better to fix it soon then let more code get written that takes advantage of this (IMHO) misfeature.
James
I certainly can live with the current implementation! It's just that I need sometimes a heads-up to get my head to think the CFFI way..
Thx!
Frank
Frank Goenninger fgoenninger@prion.de writes:
Ideally, :POINTER should probably become a parameterized type, so that function would instead be:
(defcfun struct-by-pointer :void (a (:pointer a-struct))
which will help us down the road when we implement optional pointer type checking.
Which I'd prefer also ! Let's you not only do type checking but is what I need most: As close to C as it can get. I'd have some translate-from/to-foreign functions specializing on the pointer type rather than defining a new type and dispatching on that.
I've pushed a patch adding this parameterization support for :pointer to the darcs tree. It doesn't do type checking yet, but it makes the code more readable (and is backwards compatible with the old behavior).
In retrospect, the foreign type A-STRUCT should probably always mean the structure itself by value, and declaring a function like:
(defcfun struct-by-value :void (a a-struct))
should probably just be an error, instead of the DWIM-ish behavior of canonicalizing A-STRUCT to :POINTER.
It certainly would be more puristic and IMHO clean.
Unless there are any objections, I think I will make this (and FOREIGN-SLOT-VALUE on aggregates) issue a warning that the behavior will change in a future release, with a short description of how to rewrite it correctly.
James