Tip: if you use scheme-pointer instead of c-pointer, you can omit the
locative). E.g. (make-blob size) instead of (location (make-blob size)). This
will be faster.
On Jun 25, 2012, at 5:27 PM, Kristian Lein-Mathisen wrote:
>
> Hi guys!
>
> It's me again, still going on about struct-by-value in chicken-bind. This
> time I think I may have code worthy of entering the official repo. The
> patches add three new features:
> Struct-by-value in arguments
> Struct-by-value return types
> Nested structs (practically same as 2)
> Functions on the Scheme-side interface all functions using pointers or
> locatives, regardless of their original signature.
>
> You can have a look at my 10 commits that make up the patch on github. I
> tried to be descriptive in my commit messages. Please let me know of your
> thoughts and concerns. If nothing pops up, I'll pass it on Felix
> (chicken-bind maintainer) for review.
>
> Motivation
> While most C libraries pass structs by reference, both physics engines I've
> come across, Chipmunk and Box2D, pass small structs like 2d-vectors around by
> value everywhere. This patch made my life easier.
>
> Code samples
> Let's walk through the new foreign-lambda snippets that it generates. I use
> the point struct in my examples, pretend it's some 2d/3d vector of floats.
> First, let's look at passing a struct by reference:
>
> 1. Struct arguments
> [klm@kth chicken-bind]$ echo "float length(struct point*)" | chicken-bind -
> -o -
> (begin
> (begin
> (define length
> (foreign-lambda float "length" (c-pointer (struct "point"))))))
>
> Nothing's changed there, my patch will kick in when you pass structs by
> value. The patch checks if any arguments are non-pointer struct arguments,
> and if there are any, it wraps the call in a foreign-lambda* with all
> struct-by-val arguments to c-pointer variant which are dereferenced in C:
>
> [klm@kth chicken-bind]$ echo "float length(struct point)" | chicken-bind - -o
> -
> (begin
> (begin
> (define length
> (foreign-lambda*
> float
> (((c-pointer (struct "point")) a0))
> "C_return(length(*a0));"))))
>
> 2. Struct return-types
> Struct return-types are a little trickier and are split into two functions.
> One will call the original function, storing the result in a additional
> destination operand. The other will allocate memory to use as this
> destination and calls the first:
>
> [klm@kth chicken-bind]$ echo "struct point intersection(struct line*, struct
> line)" | chicken-bind - -o -
> (begin
> (begin
> (begin
> (define intersection/overwrite!
> (foreign-lambda*
> void
> (((c-pointer (struct "point")) dest)
> ((c-pointer (struct "line")) a0)
> ((c-pointer (struct "line")) a1))
> "*dest=(intersection(a0,*a1));"))
> (define (intersection a0 a1)
> (let ((dest (location
> (make-blob (foreign-value "sizeof(struct point)"
> int)))))
> (intersection/overwrite! dest a0 a1)
> dest)))))
>
> As shown above, you can mix and match struct value-passing and
> pointer-passing in the arguments.
>
> 3. Nested structs
> Nested structs face the same problem as struct return-types, but
> unfortunately I haven't looked into uniting the codebase. However, it follows
> the same destination-method as above:
>
> [klm@kth chicken-bind]$ echo "struct circle { struct point origin; float
> radius ; }" | chicken-bind - -o -
> (begin
> (define circle-origin
> (lambda (s)
> (let ((blob (location
> (make-blob (foreign-value "sizeof(struct point)" int))))
> (copy-struct!
> (foreign-lambda*
> void
> (((c-pointer (struct "point")) _dest)
> ((c-pointer (struct "circle")) s))
> "*_dest = s->origin;")))
> (copy-struct! blob s)
> blob)))
> (define circle-radius
> (foreign-lambda*
> float
> (((c-pointer (struct "circle")) s))
> "return(s->radius);"))
> (define make-circle
> (foreign-lambda*
> (c-pointer (struct "circle"))
> (((c-pointer (struct "point")) origin) (float radius))
> "struct circle *tmp_ = (struct circle *)C_malloc(sizeof(struct
> circle));\ntmp_->origin = *origin;\n\ntmp_->radius =
> radius;\n\nC_return(tmp_);")))
>
>
> Caveats
> Struct-by-value return types and nested-struct getters return locatives. This
> is nice because it will be like any other scheme-object and doesn't need to
> be explicitly freed. Be careful though, locatives will be moved around by the
> GC and thus pointers to it are not permanent.
>
> A also added a small test-suite for these features.
>
> Cheers fellow Chickeners,
> - Kris
>
> _______________________________________________
> Chicken-users mailing list
> [email protected]
> https://lists.nongnu.org/mailman/listinfo/chicken-users
_______________________________________________
Chicken-users mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/chicken-users