I thought I'd save myself some time and copy managed structure definitions and function prototypes from pinvoke.net (a great resource, by the way) rather than go through the header files and documentation myself. This wouldn't have been a problem except that I'm writing for the 64-bit platform. It appears that most of the content on pinvoke.net was submitted by programmers working on 32-bit platforms.
What's the difference? Mostly, none. Except that in many cases where the C type is SIZE_T, the corresponding type in the managed prototype or structure was UInt32. That works fine on 32-bit platforms, but in 64-bit land, SIZE_T is 8 bytes: a UInt64.
There only reliable way around the problem is to code all SIZE_T parameters, return values and structure members as the .NET type UIntPtr. Doing so ensures that the code will work properly on both platforms without change because UIntPtr is 4 bytes on 32-bit platforms, and 8 bytes on 64-bit platforms. However, it makes you cast things to and from UIntPtr in your code.
The other problem is that you'll need to use UInt64 (ulong in C#) for any variables that refer to those UIntPtr types--that is, when you do the conversion. Otherwise your code will break on 64-bit platforms.
You could write bit specific conditionals, but I don't think you'll be happy with the resulting ugliness in your code.
In any case, be very careful when converting structure members, parameters, and return types that are defined as SIZE_T.
I just realized that this issue is more involved than I can fit into a blog post of any reasonable length. I need to write a full article about it.
Take advantage of special member promotions, everyday discounts, quick access to saved content, and more! Join Today.