[plt-scheme] Re: ffi: output values

From: Eli Barzilay (eli at barzilay.org)
Date: Fri Sep 3 07:06:20 EDT 2004

I should have answered this a long time ago...  Just remembered since
the issue came up again, so I'm CCint on the list.

On Aug 23, Daniel Silva wrote:
> Given this iterator structure:
> 
>   (define-cstruct _gtk-tree-iter
>                   ([stamp _int]
>                    [user-data _int]
>                    [user-data2 _int]
>                    [user-data3 _int]))
> 
> and these two declarations:
> 
>   (define gtk-tree-model-iter-next
>     (get-ffi-obj "gtk_tree_model_iter_next" libgtk
>                  (_fun _gtk-tree-model (i : (_ptr io _gtk-tree-iter))
> -> (b : _bool) -> (values b i))))
>   
>   (define gtk-tree-model-iter-next/box
>     (get-ffi-obj "gtk_tree_model_iter_next" libgtk
>                  (_fun _gtk-tree-model (_box _gtk-tree-iter) -> _bool)))

You don't want either one, and I should probably add some warning to
the documentation about using structs and special function pointer
types.  The thing about structs is that they are always held as
pointer, but treated as blocks of data.  This means that whenever you
pass a *struct* around, the foreign library will actually move its
contents instead of the pointer.  Now, when you use (_ptr io _int) and
send an integer `foo' into a function, the following happens:
* a new _int is allocated, and `foo' is stored there,
* the function is called,
* the contents of the pointer is referenced and stored back into
  `foo'.

Now, when you do this with a struct type, the *same* thing happens,
but instead of a single integer, you have a block of data.  So, in the
first step, a new struct is allocated and the contents of `foo' is
copied over, and in the last step yet another struct is created, the
previous (end) struct is copied to this new one, and the result
assigned to the variable.

This is why whenever you define a _foo struct, you get a _foo-pointer
type that you can use with these structs -- if you use this
_foo-pointer to a foreign function, then the pointer will be sent, and
your struct might mutate (which is probably what you want with
iterators anyway).  The (_ptr _io <struct>) thing should be used when
you want to treat struct as immutable values.

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!


Posted on the users mailing list.