Answer: When PInvoke is involved.
I ran across a common error today on stackoverflow regarding P/Invoke that is worth blogging about. The question regarded the translation of a native API with a parameter of type LONG. The user mistakenly used the .Net long type as the parameter. The error is that a C++ LONG is not the same as a .Net long.
When talking about types and PInvoke it’s easier to discuss byte size and signed-ness than type names. Otherwise confusion around long and short crop up. Really there are four integer byte sizes each of which can be signed or unsigned: 1,2,4 and 8
The problem the user encountered is the C++ long is 4 byte signed and .Net long is 8 byte signed. PInvoke requires the parameters to have the same size. Below is a quick table of the various types in C++ and .Net.
- 1 byte
- C++ – char, __int8, BYTE, BOOLEAN
- .Net – byte
- 2 byte
- C++ – wchar, __int16, short, WORD
- .Net – char, short
- 4 byte
- C++ – int, LONG, long, __int32, DWORD
- .Net – int
- 8 byte
- C++ – __int64, LONGLONG, DWORDLONG, LARGE_INTEGER
- .Net – long
Based on this table when translating a C++ LONG, you should use a .Net int.
Edit1: Moved C++ short to 2 byte, added several other C++ types. (thanks Raymond)