Hi Jim,

I really appreciate you looking over this!

However, I think that it may be more practical to return locatives because
they are interchangeable with c-pointers. This makes them easier to pass
around with other parts of the foreign-code.

If we remove (locative ...) and use scheme-pointer, nested struct getters
and struct return-types in scheme would return blobs instead of locatives.
Let's check out this (untested) example of what I think would be typical
usage:

(bind "
struct point  { float x, y; };
struct circle { struct point origin; float radius; };
float distance(struct point, struct point);")

(define c1 (make-circle (make-point 10 10) 0.5))
(define c2 (make-circle (make-point 1 1) 0.2))

;; circle-origin is a nested-struct getter.
;; if it returns blobs, we must do:
(distance (make-locative (circle-origin c1)) (make-locative (circle-origin
c2)))
;; if it returns locative:
(distance (circle-origin c1) (circle-origin c2))

I was not aware of the performance penalty introduced by (locative <blob>).
Would it be beneficial to return the locative of the blob as a last step,
and use scheme-pointer in the intermediate, destination-operand, step?

Thank you,
K.



On Mon, Jun 25, 2012 at 10:18 PM, Jim Ursetto <zbignie...@gmail.com> wrote:

> 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<http://wiki.call-cc.org/eggref/4/bind>.
> This time I think I may have code<https://github.com/kristianlm/chicken-bind> 
> worthy
> of entering the official repo. The patches add three new features:
>
>    1. Struct-by-value in arguments
>    2. Struct-by-value return types
>    3. 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<https://github.com/kristianlm/chicken-bind/commits/>. 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<https://github.com/kristianlm/chicken-bind/blob/master/tests/struct-passing-tests.scm>for
>  these features.
>
> Cheers fellow Chickeners,
> - Kris
>
> _______________________________________________
> Chicken-users mailing list
> Chicken-users@nongnu.org
> https://lists.nongnu.org/mailman/listinfo/chicken-users
>
>
>
_______________________________________________
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users

Reply via email to