Hi all,
I'm trying to make a pinvoke call to a legacy c dll. One method has a
structure as input.
The managed structure looks like this:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Info
{
public Version cryptokiVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string manufacturerID;
public uint flags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string libraryDescription;
public Version libraryVersion;
}
the inner Version structure:
public struct Version
{
public byte major;
public byte minor;
}
I need this structure to have exactly 72 bytes, as this is the size of the c
counterpart. On the first look, it should have 72 bytes (2 bytes for Version
x 2 + 32 bytes for the two ansi strings x 2 + 4 bytes uint = 72).
Unfortunately, Marshal.SizeOf calculates the size of this structure as 76,
although SizeOf applied to the individual members returns the correct,
expected values...
If I remove the uint, the size from Marshal.SizeOf suddenly drops to 68,
which is equal to the manualy calculated one. A uint takes up 4 bytes though
(Marshal.SizeOf confirms this), so why did the size drop by 8 bytes, not 4?.
If I replace the uint with two shorts (which are equal in size to one uint),
the size from Marshal.SizeOf is now correctly 72 (68 + 2x2).
Is this a bug in the framework (2.0.50727), or am I doing something wrong?
Thanks in advance for any insights...

Signature
PS
TDC - 10 Aug 2006 16:32 GMT
You are having problems because of the 4-byte alignment used in
structures.
The structure legacy C dll uses a structure that has members that
stradle that alignment in several places, which leads to pad bytes
getting created.
What you really have right now is:
public Version cryptokiVersion;
PadByte1
PadByte2
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string manufacturerID;
public uint flags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string libraryDescription;
public Version libraryVersion;
PadByte3
PadByte4
Tom
> Hi all,
> I'm trying to make a pinvoke call to a legacy c dll. One method has a
[quoted text clipped - 35 lines]
>
> Thanks in advance for any insights...
TDC - 10 Aug 2006 16:45 GMT
I just checked and the default in .NET is actually a Pack of 8 bytes,
not 4.
In any case, if specifiy a Pack of 1 in your StructLayoutAttribute then
it should solve your problem.
(There are few other solutions as well).
Let us know how you make out.
Tom
> You are having problems because of the 4-byte alignment used in
> structures.
[quoted text clipped - 58 lines]
> >
> > Thanks in advance for any insights...
ps - 10 Aug 2006 17:41 GMT
Thanks a lot, adding of the Pack property fixed my problem completely!
Just a few questions if I may... Why is it that this value only gets applied
only if there is a int or uint, but in the two shorts case? Also, is there
any relation to the fact that it only gets applied after the two nested
structures?
Thanks a lot again for that, I've spent a lot of time investigating this
already, and you saved yet a lot more of it :)

Signature
PS
„TDC" napísal (napísala):
> I just checked and the default in .NET is actually a Pack of 8 bytes,
> not 4.
[quoted text clipped - 70 lines]
> > >
> > > Thanks in advance for any insights...
TDC - 10 Aug 2006 19:14 GMT
I'm not exactly sure how the embedded structures get treated (though
I'm curious and I may have to run a test to find out exactly).
As for the Uint vs 2 Shorts, it is understandable that the smaller
types yeild less padding, because there is les chance of the
"straddling" a boundry. It would only be possible if you had an odd
length and in your case all the lengths are even.
As an aside, I'm pretty sure that my previous description of exactly
where in the structre the padding was taking place, so don't ocde
relying on that. The important thing is knowing that padding is going
on.
Tom
> Thanks a lot, adding of the Pack property fixed my problem completely!
>
[quoted text clipped - 84 lines]
> > > >
> > > > Thanks in advance for any insights...
TDC - 10 Aug 2006 20:47 GMT
I wrote a quick test...the padding is as follows
public Version cryptokiVersion; <--- bytes 0,1
public string manufacturerID; <--- bytes 2 thru 33 (the
last being a trailing null)
PAD <--- bytes 34, 35 pad so that flags can start
on a 4-byte boundry
public uint flags; <--- bytes 36, 37, 38, 39
public string libraryDescription; <--- bytes 40 thru 71 (the
last being a trailing null)
public Version libraryVersion; <--- bytes 72,73
PAD <--- bytes 74, 75 pad to fill a full upto the next 4
byte boundry
Hope that helps!
Tom
> I'm not exactly sure how the embedded structures get treated (though
> I'm curious and I may have to run a test to find out exactly).
[quoted text clipped - 99 lines]
> > > > >
> > > > > Thanks in advance for any insights...
ps - 11 Aug 2006 16:32 GMT
Thank you very much,
This solved my problem and the issue is a lot clearer now.

Signature
PS
„TDC" napísal (napísala):
> I wrote a quick test...the padding is as follows
>
[quoted text clipped - 116 lines]
> > > > > >
> > > > > > Thanks in advance for any insights...
ps - 10 Aug 2006 16:52 GMT
Hi,
thanks for the quick reply!
I think you are right, as it would exactly correspond to the shift in bytes
i perceive when the structure gets filled by the legacy component. There is a
two byte shift in the manufacturerID, and the other one possibly at the end.
Why aren't the pad bytes there if I replace the uint with two shorts though?
Is there any way to tell when they will be there and at what positions? Is
there any reason for them to be there at all? :)
Are there any workarounds except the one I mentioned (the replacement works
ok, but now the structure has one more field, that is just the placeholder
for the two bytes)
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Info
{
public Version cryptokiVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string manufacturerID;
public short flags;
private short x; // dummy placeholder for 2 bytes
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string libraryDescription;
public Version libraryVersion;
}

Signature
PS
„TDC" napísal (napísala):
> You are having problems because of the 4-byte alignment used in
> structures.
[quoted text clipped - 58 lines]
> >
> > Thanks in advance for any insights...