Re: [Chicken-users] patch for chicken-bind!
Wow! Cool stuff - I'll look at that. It would be great if this were reviewed and made part of the official chicken-bind. Sure - I'll get back to you. cheers, felix ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] patch for chicken-bind
Hello! Bind 1.0 with support for passing structs by value is now available. Many thanks, Kristian, for contributing this! cheers, felix ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] patch for chicken-bind
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-bindhttp://wiki.call-cc.org/eggref/4/bind. This time I think I may have codehttps://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 githubhttps://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
[Chicken-users] patch for chicken-bind
Hi guys! It's me again, still going on about struct-by-value in chicken-bindhttp://wiki.call-cc.org/eggref/4/bind. This time I think I may have codehttps://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 githubhttps://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-suitehttps://github.com/kristianlm/chicken-bind/blob/master/tests/struct-passing-tests.scmfor these features. Cheers fellow Chickeners, - Kris ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users