On 2013-08-22, at 9:20 AM, Mikael mikael.rcv@gmail.com wrote:
Aha.
Very well, then I guess it's good time to ask Marc how this stuff works really. :))
Marc, would you feel like enlightening us on this one - how use and reclaim of non-pointered FFI structs works out?
I tested this code and it works fine:
(declare (standard-bindings) (fixnum) (not safe))
(c-declare #<<end-of-c-declare
struct point { int x; int y; };
struct point make_point( int x, int y ) {
struct point p; p.x = x; p.y = y;
return p; }
end-of-c-declare )
(c-define-type struct-point (struct "point"))
(define make-point (c-lambda (int int) struct-point "make_point"))
(define make-point2 ;; this should be equivalent but triggers a bug in Gambit (c-lambda (int int) struct-point "struct point p; p.x = ___arg1; p.y = ___arg2; ___result = p;"))
(define (alloc-points times) (let loop ((i 0)) (if (< i times) (let ((p (make-point 0 0))) (loop (+ i 1))))))
(time (alloc-points 100000000))
Deallocation of the structures is done correctly and there is no memory leak or segmentation faults. If the return type had been a C++ class, the destructor would have been called just prior to its deallocation by the GC, as expected.
There seems to be a problem however in the "inline" c-lambda form (as used in the definition of make-point2). The definition should be equivalent to the definition of make-point, but isn't. That's a bug that I will investigate.
I suggest that for the time being, you avoid using inline c-lambda forms that return structures. This means you will have to create a C function that returns a structure, and use the plain c-lambda form to interface to that C function.
Marc