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