First of all, the Boolean type has the default marshal type of a four-byte value. Thus, the following code works:
struct A
{
public bool bValue1;
public int iValue2;
}
struct B
{
public int iValue1;
public bool bValue2;
}
public static void Main()
{
int[] rawvalues = new int[] { 2, 4 };
A a = (A)Marshal.PtrToStructure(GCHandle.Alloc(rawvalues, GCHandleType.Pinned).AddrOfPinnedObject(), typeof(A));
Assert.IsTrue(a.bValue1 == true);
Assert.IsTrue(a.iValue2 == 4);
B b = (B)Marshal.PtrToStructure(GCHandle.Alloc(rawvalues, GCHandleType.Pinned).AddrOfPinnedObject(), typeof(B));
Assert.IsTrue(b.iValue1 == 2);
Assert.IsTrue(b.bValue2 == true);
}
Clearly, these structures marshal independently just fine. Values are recalculated as expected. However, when we combine these structures into a "union", declaring LayoutKind.Explicit as follows:
[StructLayout(LayoutKind.Explicit)]
struct Broken
{
[FieldOffset(0)]
public A a;
[FieldOffset(0)]
public B b;
}
We suddenly find ourselves unable to marshal these types correctly. Here is the test code for the above structure and how it fails:
int[] rawvalues = new int[] { 2, 4 };
Broken broken = (Broken)Marshal.PtrToStructure(GCHandle.Alloc(rawvalues, GCHandleType.Pinned).AddrOfPinnedObject(), typeof(Broken));
Assert.IsTrue(broken.a.bValue1 != false);
Assert.IsTrue(broken.a.bValue1 == true);
Assert.IsTrue(true.Equals(broken.a.bValue1));
Assert.IsTrue(broken.a.iValue2 == 4);
Assert.IsTrue(broken.b.iValue1 == 2);
Assert.IsTrue(broken.b.bValue2 == true);
It is very humorous to see that this expression is true: (a.bValue1! = False && aValue1 == true &! True.Equals (a.bValue1))
, , a.iValue2!= 4, 4 1 (, bool).
, : , ?
: , bool vs uint PInvoke?
: ( > 255) , , , 1, 0x0f00 0x0f01 b.bValue2. a.bValue1 , 0x0f00 a.bValue1.
# 2:
uint . " " . , , ?
struct A
{
private uint _bValue1;
public bool bValue1 { get { return _bValue1 != 0; } }
public int iValue2;
}
struct B
{
public int iValue1;
private uint _bValue2;
public bool bValue2 { get { return _bValue2 != 0; } }
}