
February 25th | 2010
Quirks in .NET Part -2 Marshalling Booleans
In Quirks in .NET – Part 1, we talked about the quirky call vs. callvirt instructions.
This week Platform Invoke is under my microscope. It isn’t necessarily a quirk, but it can be a hair-pulling experience when you get it wrong. More specifically, getting the marshaling done properly. Even more challenging, getting it right on both 32-bit and 64-bit environments.
Marshaling Booleans
Marshaling is done primarily for two reasons: you need functionality that is not built into the .NET Framework, but is found in existing Win32 APIs; and you have existing functionality in an unmanaged library you want to reuse.
Let’s start with the basics: What managed types map to unmanaged types? Some are common sense and some are not. Let’s talk about the System.Boolean type for a second.
Most people assume it takes exactly 1 bit in managed world, but in memory it’s a byte. We can prove it with this code:
int sizeBoolean = sizeof (bool); int sizeInt = sizeof (int); Console.Out.WriteLine("size of boolean = {0}", sizeBoolean); Console.Out.WriteLine("size of int = {0}", sizeInt);
The size of operator returns the value in bytes, and a bool is 1. Here’s where things get tricky. In unmanaged world, there are two types—three really—BOOL, BOOLEAN, and COM’s VARIANT_BOOL.
The .NET Framework will try guess which one you mean when marshaling, but it won’t always get it right. When a managed bool is marshaled in a Platform Invoke method, it will marshal it automatically as a 4 byte type which is the more common marshaling case. However, if you cause an interface to get marshaled to COM and that interface has a Boolean as a return or method parameter, it will marshal it automatically as a 2-byte VARIANT_BOOL. Since COM interfaces tend to mix and match Booleans of different sizes, it’s always best to be explicit about which Boolean to marshal it to using the MarshalAsAttribute attribute.
You’ll have to look at the IDL or header file of the unmanaged code to determine which you need to use. Sometimes it requires a bit of playing around too.
| Unmanaged Type | Size (in bytes) | MarshalAs Enum |
| BOOL (Win32) | 4 | UnmanagedType.Bool |
| BOOLEAN (Win32) | 1 | UnmanagedType.I1 |
| VARIANT_BOOL (COM) | 2 | UnmanagedType.VariantBool |
In Quirks in .NET – Part 3 we’ll look at numbers and binary
Nice information. I am curious for part 3, because I am working on a project which uses an unmanaged C Library, so all the quirks information about Marshaling is more then welcome;)
Glad you found it useful. Part 3 will cover marshalings strings, which can be very tricky
.
[...] Quirks in .NET – Part 2, we looked at marshaling Booleans to Win32 and COM. Now, let’s talk about numbers and [...]