chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] bind egg and strings


From: Andrei Barbu
Subject: Re: [Chicken-users] bind egg and strings
Date: Thu, 14 Mar 2013 03:23:25 -0400

On Fri, Feb 15, 2013 at 5:53 AM, Felix
<address@hidden> wrote:
> From: Andrei Barbu <address@hidden>
> 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

Attachment: bind-string.diff
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]