Version: Unity 6.6 (6000.6)
Language : English
Native plug-ins
Call functions

Introduction to native plug-ins in Unity

A native plug-in is a library of unmanaged code that provides a C interface you can access from managed C# scripts.

Unity native plug-in support uses the standard .NET platform invoke (Microsoft) feature. This feature lets C# code call unmanaged functions that native code libraries export. It uses a process called marshalling (Microsoft) to transfer data between managed and unmanaged code.

For an example of a native plug-in, refer to SimplestPluginExample (Unity Technologies on GitHub).

Native plug-in forms

You can import native plug-ins into a Unity project in the following forms:

  • Binary files precompiled for specific platforms and CPU architectures.
  • Source code files, which Unity compiles as part of your project build process.

Unity supports precompiled static libraries on Android, Apple mobile platforms (iOS, tvOS, and visionOS), and the Web platform. Desktop platforms don’t support precompiled static libraries.

Unity statically links plug-ins that you import as source code files. Unity supports source code plug-ins only in projects that use the IL2CPP scripting backend. Source code plug-ins don’t work in Editor scripts or in Play mode.

After you import plug-in files into your Unity project, set the properties that determine which platforms the plug-in is compatible with and when the library loads. To do this, select the imported files in the Project window and set the relevant properties in the Inspector window. For more information, refer to Change plug-in settings.

Important: After the Editor loads a native plug-in, either through an Editor script or in Play mode, it can’t unload the plug-in. To update a native plug-in after the Editor loads it, restart the Editor. Otherwise, the Editor continues to use the loaded version of the plug-in instead of the updated version.

Function exports and declarations

To work in Unity, a native plug-in must export its external functions using C linkage. This type of linkage avoids C++ name mangling and other Application Binary Interface (ABI) issues.

To access an unmanaged function from managed C# code, declare a C# static extern function with the same name and compatible return and parameter types, then call it like any other method. For the full declaration rules and examples, refer to Call functions.

Interoperation with a native plug-in

The scripting runtime manages the C# code that you write in Unity. The scripting runtime manages where data is stored in memory, and routinely moves data around to avoid memory fragmentation. Unmanaged code in a native plug-in handles its own memory directly and can use pointers to address specific memory locations. When you write managed code that interoperates with unmanaged code, be careful about where the data is stored, when the data is accessed, and which side is responsible for freeing memory that’s no longer needed.

Managed code and native code can represent some data types in different ways. .NET provides an interop marshaller that provides a default representation and conversion for most types. When the default behavior is incorrect or suboptimal, use the following attributes from the .NET Interop Services API to define the representation and conversion of specific data types:

For more information, refer to Pass data between managed and unmanaged code introduction.

Interoperation between managed and unmanaged code is a complex topic. For a more thorough explanation, refer to the following .NET documentation:

Call a function in a native plug-in

A simple C native library with a single function might contain the following code:

float ExamplePluginFunction()
{
    return 5.0F;
}

Note: This minimal example omits the export annotation for brevity. A precompiled dynamic library, such as the one that the following example imports with [DllImport("PluginName")], must export its functions. For the EXPORT_API annotation that exports a function on each platform, refer to Call unmanaged functions from managed code.

If you compile this code separately and import the compiled library into your Unity project, you can use the following C# script to call ExamplePluginFunction:

using UnityEngine;
using System.Runtime.InteropServices;

class ExampleScript : MonoBehaviour
{
    // Use the library file name for dynamically linked libraries.
    [DllImport("PluginName")]
    private static extern float ExamplePluginFunction ();

    void Awake()
    {
        // Call ExamplePluginFunction inside the plug-in.
        Debug.Log(ExamplePluginFunction());
        // The Console window displays 5.
    }
}

If you import the native code as source code, use __Internal in the DllImport attribute instead of the library name:

using UnityEngine;
using System.Runtime.InteropServices;

class ExampleScript : MonoBehaviour
{
    // Use __Internal instead of the library name for source-code plug-ins.
    [DllImport("__Internal")]
    private static extern float ExamplePluginFunction ();

    void Awake()
    {
        // Call ExamplePluginFunction inside the plug-in.
        Debug.Log(ExamplePluginFunction());
        // The Console window displays 5.
    }
}

For more information on how to identify the native plug-in library to load, refer to DllImport attribute.

Additional resources

Native plug-ins
Call functions