[plt-scheme] Eli Barzilay's new FFI stuff

From: Eli Barzilay (eli at barzilay.org)
Date: Sat Aug 7 02:33:49 EDT 2004

On Aug  6, Christopher Armstrong wrote:
> I've been having great success with your FFI so far, it's very nice!
> :-)

Very nice to hear that.

> However, I need support for inheritance in define-cstruct.  Should I
> 1) try to add it to your define-cstruct macro and send you a patch*
> or 2) create my own define-subbable-cstruct macro that simply calls
> define-cstruct?

Well, adding inheritance to define-cstruct is certainly something I
want to add at some point, but it's a little tricky.  By itself, it
wouldn't be too hard, but I'm worrying for duplicating stuff that
define-struct can already do, so I kind of got stuck at the stage of
"think about some way to avoid reimplementing structs".  The main
thing is the additional syntactic information.  More below.

> * this will be hard, as your define-cstruct is huge and I am not very
> good with define-syntax and syntax-case :)

It's not too hard to follow.  The best way is probably to just expand
a few usages and see what the output does.

> The advice I got from fellow Schemers was that a good way to do the
> interface would be to make either define-cstruct or
> define-subbable-cstruct produce define-<name>-substruct that works
> like this:
> (define-cstruct _structname
>   ([x _typ]))
> (define-structname-substruct _substructname
>   ([y _typ]))

Well, a better approach is to follow the way define-struct is used, so
instead of the above you'd do this:

  (define-cstruct (_structname _substructname)
    ([y _type]))

> which would expand to
> (define-cstruct _substructname
>   ([x _typ]
>    [y _typ]))
> Do you agree that this is a good way to do it?

That would be the preferred way, because it will behave like
define-struct.  For example, you will get a new substructname-x
function.  On the technical side, there is the issue of the pointer
tag -- you want to use a tag that will make these things acceptable
instances of _structname too.  I have a way to get this done so this
is not a big problem.

The thing is that you need to keep around some syntactic information
around too -- if you want this expansion to happen, it means that when
you define _substructname, the syntax expander needs to know how
_structname was defined.  MzScheme keeps the syntactic level seperate
from the runtime environment, so everything must be clean.  This
additional information will not be too difficult to implement, but
it will most likely run into some subtle problems.  This is why I was
trying to think of some way of taking advantage of the normal

Now, note that since this is specifying simple memory layouts, you
could in many cases fake it in the same way that you can do it in C:

  (define-cstruct _substructname
    ([super _structname]
     [y _type]))

The disadvantage is that to access the `x' slot of an instance of
substructname, you have to use structname-x, which is confusing -- but
this is fine because define-struct does just this.  The reason I said
"many cases" is that I'm not sure if there can some alignment problems
that will make `foo' have different layouts if you use:

  typedef struct {
  } foo;


  typedef struct {
  } foo_parent;
  typedef struct {
    foo_parent super;
  } foo;

Intuitively, I think that this should always be the same, but I'm not
sure.  Do you know if these can be different?  It will simplify things
if this works.

> Also, not that I'm familiar with what's considered sensible in the
> Scheme community, but I found it confusing that (define-cstruct
> _name ([x _typ])) produces name-x as a member getter instead of
> _name-x....  But that's not a big problem, of course.

This is intentional.  I want a clear separation from the object's
interface from a Scheme point of view (foo?, make-foo, foo-x) and it's
C representation (the _foo type).  This is similar to `_string' vs
`string?', `string-ref' etc.  Note that define-struct is doing
something similar:

  > (define-struct foo (x))
  > struct:foo

The thing with cstruct si that the generated type object is needed in

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

Posted on the users mailing list.