On Fri, Feb 15, 2013 at 5:53 AM, Felix <[email protected]> wrote: > From: Andrei Barbu <[email protected]> > Subject: Re: [Chicken-users] bind egg and strings > Date: Mon, 11 Feb 2013 02:04:16 -0500 > >> Attached is a trivial patch that does the strdup. >> >>> I've been using the bind egg and encountered some strange behaviour. >>> I have: >>> >>> struct a { >>> char *b; >>> }; >>> >>> Bind generates: >>> >>> (begin >>> (define a-b >>> (foreign-lambda* c-string (((c-pointer (struct "a")) s)) >>> "return(s->b);")) >>> (define make-a >>> (foreign-lambda* >>> (c-pointer (struct "a")) >>> ((c-string b)) >>> "struct a *tmp_ = (struct a *)C_malloc(sizeof(struct >>> a));\ntmp_->b = b;\n\nC_return(tmp_);"))) >>> > No, you're not missing anything. A strdup is perhaps not the perfect > solution, since you can never now what the user intended, and whether > this is a temporary data structure or a permanent one. The generated > code should probably take a c-pointer argument and leave it the user > to create a statically allocated string and convert it to a pointer.
Having to do the static allocation manually all the time when all you
want is an strdup is rather unpleasant.
How about a patch that does both?
This patch allows you to pass in either a string (will do an strdup)
or a pointer to make-<structure-name>.
<structure-name>-<field-name> performs the strdup as above when
setting the field and returns a string when getting it.
<structure-name>-<field-name>* takes a pointer and fetches a pointer.
This gives the user the option of either behaviour.
With mutable fields given:
struct a {
char *b;
};
bind currently generates:
(begin
(define a-b
(getter-with-setter
(foreign-lambda* c-string (((c-pointer (struct "a")) s)) "return(s->b);")
(foreign-lambda*
void
(((c-pointer (struct "a")) s) (c-string x))
"s->b = strdup(x);")))
(define make-a
(foreign-lambda*
(c-pointer (struct "a"))
((c-string b))
"struct a *tmp_ = (struct a *)C_malloc(sizeof(struct
a));\ntmp_->b = strdup(b);\n\nC_return(tmp_);")))
This patch modifies it to generate:
(begin
(define a-b
(getter-with-setter
(foreign-lambda* c-string (((c-pointer (struct "a")) s)) "return(s->b);")
(foreign-lambda*
void
(((c-pointer (struct "a")) s) (c-string x))
"s->b = strdup(x);")))
(define a-b*
(getter-with-setter
(foreign-lambda*
c-pointer
(((c-pointer (struct "a")) s))
"return(s->b);")
(foreign-lambda*
void
(((c-pointer (struct "a")) s) (c-pointer x))
"s->b = x;")))
(define-foreign-type
bind-string
c-pointer
(lambda (a)
(if (string? a)
((foreign-lambda* c-pointer ((c-string a)) "C_return(strdup(a));") a)
a))
(foreign-lambda* c-string ((c-pointer a)) "C_return(a);"))
(define make-a
(foreign-lambda*
(c-pointer (struct "a"))
((bind-string b))
"struct a *tmp_ = (struct a *)C_malloc(sizeof(struct
a));\ntmp_->b = b;\n\nC_return(tmp_);")))
This introduces the foreign-type 'bind-string' to make
make-<structure-name> work. It's a bit of a wart that each structure
reintroduces this foreign type, but that doesn't matter as all
'bind-string' definitions are identical.
Andrei
bind-string.diff
Description: Binary data
_______________________________________________ Chicken-users mailing list [email protected] https://lists.nongnu.org/mailman/listinfo/chicken-users
