rendered paste bodyusing System;
using System.Runtime.InteropServices;
class Test {
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, "#1");
Assert.IsTrue (a.iValue2 == 4, "#2");
B b = (B) Marshal.PtrToStructure (GCHandle.Alloc (rawvalues, GCHandleType.Pinned).AddrOfPinnedObject (), typeof (B));
Assert.IsTrue (b.iValue1 == 2, "#3");
Assert.IsTrue (b.bValue2 == true, "#4");
Broken broken = (Broken) Marshal.PtrToStructure (GCHandle.Alloc (rawvalues, GCHandleType.Pinned).AddrOfPinnedObject (), typeof (Broken));
Assert.IsTrue (broken.a.bValue1 != false, "#5");// pass, not false
Assert.IsTrue (broken.a.bValue1 == true, "#6");// pass, must be true?
// This one fails because the end result is comparing 2 to 1 (see the IL above)
//Assert.IsTrue (true.Equals (broken.a.bValue1), "#7");// FAILS, WOW, WTF?
// The following works fine
Assert.IsTrue (broken.a.iValue2 == 4, "#8 " + broken.a.iValue2, broken);// FAILS, a.iValue1 == 1, What happened to 4?
Assert.IsTrue (broken.b.iValue1 == 2, "#9");// pass
Assert.IsTrue (broken.b.bValue2 == true, "#10");// pass
}
}
struct A {
[MarshalAs (UnmanagedType.Bool)]
public bool bValue1;
public int iValue2;
}
struct B {
public int iValue1;
[MarshalAs (UnmanagedType.Bool)]
public bool bValue2;
}
[StructLayout(LayoutKind.Explicit)]
struct Broken {
[FieldOffset(0)]
public A a;
[FieldOffset(0)]
public B b;
[FieldOffset(0)]
public byte B0;
[FieldOffset(1)]
public byte B1;
[FieldOffset(2)]
public byte B2;
[FieldOffset(3)]
public byte B3;
[FieldOffset(4)]
public byte B4;
[FieldOffset(5)]
public byte B5;
[FieldOffset(6)]
public byte B6;
[FieldOffset(7)]
public byte B7;
}
static class Assert {
public static void IsTrue (bool t, string msg)
{
if (!t)
Console.Error.WriteLine (msg);
}
public static void IsTrue (bool t, string msg, Broken broken)
{
if (!t) {
Console.Error.WriteLine (msg);
Console.WriteLine ("\t{0}", broken.B0);
Console.WriteLine ("\t{0}", broken.B1);
Console.WriteLine ("\t{0}", broken.B2);
Console.WriteLine ("\t{0}", broken.B3);
Console.WriteLine ("\t{0}", broken.B4);
Console.WriteLine ("\t{0}", broken.B5);
Console.WriteLine ("\t{0}", broken.B6);
Console.WriteLine ("\t{0}", broken.B7);
}
}
}