All pastes #1665189 Raw Edit

Marshal, structures and bool

public text v1 · immutable
#1665189 ·published 2009-11-10 18:21 UTC
rendered paste body
using 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);
		}
	}
}