[gambit-list] Proper usage of ffi structs

Chris Mueller ruunsmail at gmail.com
Wed Aug 21 17:15:01 EDT 2013


I'm opening a new subject for the ffi struct issue to sum up the current 
discussion:

In 19.1 "The Mapping of types between C and Scheme" of the gambit 
documentation is mentioned:

"In the case of the struct, union and type types, the default function 
reclaims the copy on the C heap referenced by the internal pointer (when 
using a C++ compiler this is done using ‘delete 
(type*)internal-pointer’, which calls the destructor of type if it is a 
class) and returns ‘___FIX(___NO_ERR)’. In many situations the default 
release-function will perform the appropriate cleanup for the foreign 
type."

If i interpret this correctly, a declared struct type in a ffi provides
a default release function that automatically calls a destructor (used 
with g++) and frees the corresponding memory.

Unfortanetly, i'm little lost to use it correctly and experiment 
currently heavily to find the right way.


Assume a type:

(c-declare "struct point { int x; int y; };")
(c-define-type struct-point (struct "point"))


Assume a test programm that allocates a point 1_000_000_000 times.

(define (alloc-point times)
   (let loop ((i 0))
      (if (< i times)
        (let ((a (make-point 0 0)))
          (loop (+ i 1)))))))

(alloc-point 1000000000)


How do we implement (make-point x y) to use a ffi struct type with a 
default release function in Gambit?

1) With a manually allocated pointer it will leak memory.

(define make-point
   (c-lambda (int int) struct-point
     "point* a = new Point;
      a->x = ___arg1;
      a->y = ___arg2;
      ___result_voidstar = a;"))

2) With a stack-allocated value it will segfault immediately.

(define make-point
   (c-lambda (int int) struct-point
     "point a;
      a.x = ___arg1;
      a.y = ___arg2;
      ___result = a;"))

3) If we give the address of a stack-allocated value to 
___result_voidstar the allocation loop is running with constant memory 
space but the programm will segfault after quiting with CTRL + X.

(define make-point
   (c-lambda (int int) struct-point
     "point a;
      a.x = ___arg1;
      a.y = ___arg2;
      ___result_voidstar = &a;"))


For more details, see discussion:
https://mercure.iro.umontreal.ca/pipermail/gambit-list/2013-August/006950.html


Chris


More information about the Gambit-list mailing list