chicken-users
[Top][All Lists]
Advanced

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

Re: [Chicken-users] Re: FFI to libgmp questions


From: felix
Subject: Re: [Chicken-users] Re: FFI to libgmp questions
Date: Sat, 29 Jun 2002 23:31:21 +0200

>> `C_alloc()' allocates memory on the C-stack. After returning from
>> this procedure, the memory is invalid! `C_alloc()' should only be called
>> in CPS-converted code, i.e. that was Chicken produces.
>> Another thing is that a value of return-type `c-string' is always copied,
>> so the `arena' buffer above will be copied again, leaking memory again
>> (if we would have used `mallloc()' instead of `C_alloc()').
>
>So I don't understand the difference between my implementation above and yours.
>(Though I accept your version and will change my code to use it).
>
>In your version, it is just "given" that the c-string is copied into
>memory and I see now what you meant by doing that. However, wouldn't my
>implementation do the same thing? The memory would have been declared
>on the stack then during the return will have been copied into the gc,
>and then the stack frame goes away taking the C_alloc memory with it.
>

The problem is that the `C_alloc()' reserves space on the stack, which
will, at the point where the foreign-lambda*-code returns, be invalid, that is,
it will be in an area of stack-space that is considered "dead". This has
two implications:
- Code in interrupts, which can happen at any time, might use this space.
- The stack-space will be used by the actual copying-code even before
   it is used.

(Remember that `C_alloc()' is just a shorthand for `alloca()')

For example, your foreign-lambda* will be called like this
(`stub2()' is the actual code, will probably be named differently):

static void f37(C_word c,C_word t0,C_word t1){
C_word tmp;
C_word t2;
C_word t3;
C_word *a;
t2=(C_word)stub2(((C_word*)t0)[4],((C_word*)t0)[3],t1);
C_trace("##sys#peek-c-string");
t3=C_retrieve(lf[1]);
((C_proc4)C_retrieve_proc(t3))(4,t3,((C_word*)t0)[2],t2,C_fix(0));}

Since Chicken generates CPS code, the stack grows at every
call. The `C_trace()' invocation here might already write into the stack-space.
But the invocation of the copier (`##sys#peek-c-string') will definitely
overwrite it.

>> (define c-pointer->c-string
>>   (foreign-lambda* c-string ((c-pointer ptr)) "return(ptr);") )
>> 
>> (define mpz_get_str
>>   (let ([alloc (foreign-lambda c-pointer "mpz_get_str" pointer int mpz_t)]
>> [free (foreign-lambda void "free" c-pointer)] )
>>     (lambda (ptr base mpz)
>>       (let ([c-ptr (alloc ptr base mpz)])
>> (if (not ptr)
>>      (let ([c-str (c-pointer->c-string c-ptr)])
>>        (free c-ptr)
>>        c-str)
>>      c-ptr) ) ) ) )
>> 
>
>Don't you mean:
>>      c-ptr) ) ) ) )
>to be:
>>        ptr) ) ) ) )
>
>If not, then why not? When I do that, I get back a pointer-like object
>in chicken instead of a string.

Absolutely. My example was incorrect. My apologies.

>
>> This is a little bit confusing. Sorry.
>
>It is ok. Maybe through the efforts of people on this mailing list, the manual
>can be fleshed out somewhat to hold more wisdom about the FFI.


There definitely is a lot of work to do.

BTW, I will add two new foreign type specifiers:

(c-pointer X)
  The same as (pointer X), but more consistent, because `pointer'
  is not the same as `c-pointer'.

c-string*
  The same as `c-string', but will `free()' the returned ptr as soon as
  the contents have been copied.

>
>> P.S. External enums can be quite simply accessed, using
>> `define-foreign-variable':
>> 
>> (define-macro (define-foreign-enum . items)
>>   `(begin
>>       ,@(map
>>                 (match-lambda
>>                     [(name realname) `(define-foreign-variable ,name int 
>> ,realname)]
>>                     [name `(define-foreign-variable ,name int)] )
>>                 items) ) )
>> 
>> ; so for "enum {abc=3, def};" we would have:
>> 
>> (define-foreign-enum abc def)
>
>Can this be done in the R5RS define-syntax, etc, system?


(define-syntax define-foreign-enum
  (syntax-rules ()
    [(_ "1" (name realname))
     (define-foreign-variable name int realname) ]
    [(_ "1" name)
     (define-foreign-variable name int) ]
    [(_ item ...)
     (begin (define-foreign-enum "1" item) ...) ] ) )


cheers,
felix





reply via email to

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