Slava, one of my colleagues, asked me to help him out on a strange
issue: he's integrating an old 2D vector engine (written in C++/MFC)
into a new .NET 1.1 WinForms application. The vector engine exposes an
API through a native DLL export, along with a bunch of structures. The
issue was with unmarshalling one of the native structures: everything
seemed to be unmarshalling correctly except for the
double values (we got things like 2.53e-250 - uuh, not likely).
Slava's already managed to consume the same DLL successfully from
Delphi, and upon reviewing the two we couldn't find any difference.
What we managed to miss at first was that the Delphi marshalled
structure was declared with a {$a-} prefix, which means "ignore alignment" - otherwise Delphi might assume that the structure might be in some way memory-aligned.
Figuring that our .NET woes might be due to the same issue, a quick look around MSDN revealed to us that the StructLayoutAttribute(LayoutKind.Sequential) declaration also relied on the "pack"
member of the same class, which "controls the alignment of data fields
of a class or structure in memory." My logical conclusion as a
programmer would be that creating a sequential structure would default
to a straighforward memory representation - i.e. no alignment - but
apparently it's misguided; .NET defaults to 8-byte alignment for
managed structures. We set the alignment size to 4 and voila - problem
solved.
This only goes to prove that even the simplest and subtlest of
programming challenges can baffle even experienced developers, and both
Slava and I wasted quite a bit of time on this issue. The moral? There
isn't one, really; just expect to be baffled now and then no matter
what you've seen or been through.