[cffi-devel] Enums, structs, and field sizes

Dan Knapp dankna at gmail.com
Sat Jul 15 19:06:03 UTC 2006


  I just uncovered this issue with cffi-net.  This is more of a design
question than a bug; I know at least one way that I could work around
it, but it's distressingly inelegant.

  To get the cffi-net low-level primitives up and running, we feed
cffi-grovel the names of some preprocessor constants which it turns
into an enum called address-family, with values such as :af-inet -> 2.
 This enum is used as a parameter to a bunch of different function
calls, and it's also a member of the struct sockaddr-in.  We tell the
groveller that the "family" slot should be of the type address-family,
so instead of figuring out the size of it and putting in :uint8,
:uint16, or whatever, it declares the slot to be of type
address-family.

  The problem is that the slot of course has a correct size.  In this
case it happens to be :uint8.  In the absence of other guidance, cffi
assumes that an enum type should be a regular integer, which seems to
wind up as :sint32.  So when it comes time to access the slot, too
much memory is used and it overwrites adjacent slots.

  Since cffi does provide the option to give a base type for the enum,
we could specify that type.  If we do that by hand, though, it defeats
the purpose of having cffi-grovel; it would introduce a portability
issue and would have to be manually maintained for new architectures
with surprising new slot sizes.  We could make cffi-grovel smart
enough to notice that the enum is used for a slot, and take some
appropriate action.  It could set the base type of the enum, but this
would cause trouble with the functions that use it as a parameter type
and expect it to be int-sized.  It could create a new enum,
address-family-uint8, that duplicates everything in address-family but
is a different size.  This has the benefit of working, so if we can't
come up with anything better it's probably what we'll do.

  We also can't reasonably hook in any special-case code for when this
field is accessed, because cffi only dispatches on type when it's
deciding how to access a field, and if we create a new type we're back
to one of the above scenarios.

  It occured to me that the reason this is a problem at all is that
enums are considered to be types.  Perhaps they really need to be
something outside the type system, that can be overlayed on a type as
needed?

  Anyway, since there's no particular hurry, we thought we'd post to
the list and ask for suggestions.  It would be comforting to find a
clean way to do this.

-- 
Dan Knapp



More information about the cffi-devel mailing list