To call an unmanaged function from managed code, declare a function prototype in C# with the following characteristics:
static.extern.DllImportAttribute that identifies the native library location.You can place these managed declarations anywhere in your C# code. For example, you can declare them all in a single class, or declare individual functions in the separate classes that use them.
Note: When an unmanaged function returns a structure by value, that structure must be blittable. Blittable types have the same representation in managed and unmanaged memory, and include primitive numeric types and structs that contain only blittable types. You can return other types, such as bool and string, if you specify how to marshal them. For more information, refer to Pass data between managed and unmanaged code.
The unmanaged function must use C linkage. C linkage avoids name mangling and other Application Binary Interface (ABI) issues that arise with C++ linkage.
For example, a native plug-in might define the following function. You can copy this code directly into a C++ source code file in your Unity project, which Unity compiles and links statically:
#include <stdio.h>
extern "C" {
void SendString(const char* message) {
// The output appears in the Player log file.
printf("%s\n", message);
fflush(stdout);
}
}
To build the same code as a precompiled dynamic library, you must also export each function so the dynamic loader can find it. Define an export macro and prefix each exported function with it, for example EXPORT_API void SendString(...). A statically linked source code plug-in doesn’t need this annotation.
// Select the annotation by target platform, not by compiler.
// Every Windows compiler (MSVC, MinGW, and Clang) needs __declspec(dllexport) to export from a DLL.
// GCC and Clang use the visibility attribute on other platforms.
#if defined(_WIN32)
#define EXPORT_API __declspec(dllexport)
#elif defined(__GNUC__) || defined(__clang__)
#define EXPORT_API __attribute__((visibility("default")))
#else
#define EXPORT_API
#endif
Note: On 32-bit Windows, a precompiled dynamic library also requires the managed and unmanaged code to use the same calling convention. For the STDCALL macro that matches the default convention Unity uses, refer to Call managed functions from unmanaged code. Apply the macro the same way as EXPORT_API, for example EXPORT_API void STDCALL SendString(...).
Your C# class can declare the managed function prototype for the SendString function as follows:
[DllImport("__Internal")]
private static extern void SendString(string message);
For more information on how to identify the native plug-in library to load, refer to DllImport attribute.