[plt-scheme] ffi: cant define (_ptr o _int)

From: Eli Barzilay (eli at barzilay.org)
Date: Sun Jul 9 04:29:35 EDT 2006

On Jul  8, Jon Rafkind wrote:
> With ffi I cant seem to do
> (define output-int (_ptr o _int)) or anything like that. Why is this?
> This fails:
> (define output (_ptr o _int))
> (define blah (get-ffi-obj "blah" lib (_fun output -> _int)))
> (blah)

Note that this:

  (define blah (get-ffi-obj "blah" lib (_fun (_ptr o _int) -> _int)))

would work.  But this is suspicious -- this call would malloc an int
on every use and never look at the result, so my guess is that this:

  (define junk-int (_malloc _int))
  (define blah (get-ffi-obj "blah" lib (_fun (_pointer = junk-int) -> _int)))

is more suitable -- it always uses the same location but you're not
interested in the result anyway.

Back to your problem:

> So I tried:
> (define (output) (_ptr o _int))
> (define blah (get-ffi-obj "blah" lib (_fun (output) -> _int)))
> (blah)

This will fail in the same way as the above.  The thing is that `_ptr'
is one of those "custom types" (which can get confusing, I know).
Such types are special in that they can interact in arbitrary ways
with generating the glue code -- which is how (_ptr o ...) marks an
automatically generated input so it does not correspond to an argument
of the generated Scheme procedure.  The thing is that some of these
types can (*sometimes*) be useful as plain types.  In the case of
(_ptr o _int), it expands to this description:

      (type: _pointer
       pre:  (malloc _int)
       post: (x => (ptr-ref x _int)))

which, if used in a _fun expression, means that when you call the
function, just use the malloced pointer (don't expect an argument),
and then dereference it as an int.

It can also be used as a plain type -- these types have a base type, a
function that translates values into that type, and a function to
translate them back -- in this case the base type is _pointer, the
function to translate such values (when going from C to Scheme)
derefrences the pointer, but there is no way to use it to send a value
from Scheme to C (this is the nature of an output pointer) so you get
an error for that direction:

  > (blah 'whatever)
  _ptr: cannot be used to send values to C

Now the question is, of course, why does `blah' expect an input?  The
thing is that your _fun is used with some C type objects, but such
objects correspond to values -- it might be possible to mark some of
these type objects as "when you see me in an input to a function, just
ignore me: use this value instead" -- but this is not possible to do
in the general case where there can be an arbitrary correspondence
between Scheme types and C types (eg, `bytes' on the Scheme side, vs
`char* and a length' in the C side).

Like I said, I know that this is all complex -- it's all due to such
cases where there is no 1:1 mapping between Scheme inputs and C
inputs.  A side argument would be that the only alternative I could
think of was heavy use of higher-order functions -- but not only will
this be much slower (until mzscheme's compiler is much stronger), it
will also be just as complicated if it handles the same issues.

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

Posted on the users mailing list.