Version: Unity 6.0 (6000.0)
Language : English
Pass data between managed and unmanaged code introduction
Structures, classes, and unions

Match primitive types between C# and native code

Primitive types are small value types that the runtime copies to the stack or a CPU register when you use them as function parameters or return values. You don’t need to pin or otherwise manage the lifespan of primitive types when you call unmanaged functions.

C# has different names for many primitive types compared to C and other languages. For a full list of the unmanaged C types that correspond to managed C# types, refer to Platform invoke data types (Microsoft).

The following table shows the C type that some common C# types marshal to by default:

C# base type C# alias name Unmanaged C type
System.Int32 int int32_t
System.Single float float
System.Char char char
System.Boolean bool int32_t
System.Byte byte unsigned char

Default marshalling is a starting point, not a guarantee. It can vary by platform and by context, such as whether the value is a parameter, a return value, or a struct field. For example, System.Boolean marshals to a 4-byte value by default, and System.Char marshals according to the CharSet of the call. To control the exact representation when the default isn’t what you need, use MarshalAsAttribute (Microsoft).

Use fixed-width types in unmanaged code

Use fixed-width C types, such as int32_t from <stdint.h>, in your unmanaged code rather than int or long. The size of long in particular varies by platform: it’s 32-bit on Windows but 64-bit on most other desktop and mobile platforms. If the managed and unmanaged code disagree about the size of a type, the data is corrupted.

Additional resources

Pass data between managed and unmanaged code introduction
Structures, classes, and unions