Version: Unity 6.3 LTS (6000.3)
Language : English
DllImport attribute
Primitive types

Pass data between managed and unmanaged code

When you’re passing data between managed and unmanaged code, you need to consider how the data is stored and managed in memory. This topic explains how to pass data between managed and unmanaged code in Unity.

When you pass data between functions, parameters and return values can be copied to the stack or stored in the heap. The stack is typically used for value types, and the data persists for the duration of the function call. Data with a less predictable lifespan is stored on the heap. In C#, the scripting runtime manages the heap, which involves moving data and freeing memory that’s no longer in use. In unmanaged code, you directly request and manage heap memory.

When you call an unmanaged function from managed code or a managed function from unmanaged code, both sides can directly access stack data. Therefore, you can pass small value types like float and int without extra precautions. You don’t have to worry about the data disappearing before the other side of the call accesses it.

However, when you pass reference types and larger value types, such as strings, arrays, and some structs, the data might be stored on the heap. In this case, only a reference or pointer is passed between managed and unmanaged code. You must ensure that the data remains at the same memory location for as long as it might be accessed.

For the duration of a normal call into unmanaged code, the scripting runtime handles this for you. As part of marshalling, it keeps the relevant managed data alive and in place until the call returns. You only need to take extra measures for advanced scenarios where unmanaged code retains a reference to the data and accesses it after the call returns, such as an asynchronous callback or a pointer that the native code stores for later use. In those cases, you can use the GCHandle structure to “pin” an object in memory. The scripting runtime won’t move or free a pinned object until you dispose of the GCHandle.

 //Create a GCHandle to pin data in memory
 GCHandle handle = GCHandle.Alloc(yourObject, GCHandleType.Pinned);
 //... pass data to unmanaged code that retains it beyond the call ...
 handle.Free(); //Dispose of the handle when unmanaged code is finished

For examples of passing different types of data, refer to the following topics:

Topic Description
Primitive types How to pass primitive value types like int, float, and char.
Structures, classes, and unions How to pass complex types.
NativeArrays How to pass NativeArray objects.
Strings How to pass string objects.
DllImport attribute
Primitive types