Call managed functions from unmanaged code
Register a static C# method as a callback so unmanaged code in a native plug-in can call back into managed code.
읽는 시간 2분최근 업데이트: 3일 전
To call a managed function from unmanaged code, pass a function pointer to the unmanaged code. Use a delegate to define the signature of the callback function. The callback function must be static and have an that indicates the matching delegate type.
AOT.MonoPInvokeCallbackAttributeRegister a managed callback
The following C# example defines a delegate type and a static callback function, and passes the callback to the unmanaged function:
RegisterMyCallbackusing System;using System.Runtime.InteropServices;using UnityEngine;public class PluginImport : MonoBehaviour{ delegate void MyFuncType(); [AOT.MonoPInvokeCallback(typeof(MyFuncType))] static void MyFunction() { Debug.Log("Got a call back from native code."); } [DllImport("__Internal")] static extern void RegisterMyCallback(MyFuncType func); // Keep a reference to the delegate so the garbage collector doesn't collect it // while native code still holds the function pointer. static MyFuncType s_callback; void Start() { s_callback = MyFunction; RegisterMyCallback(s_callback); }}
Receive the callback in unmanaged code
The unmanaged code must define a function pointer type that corresponds to the C# delegate. It must also export a function that receives the pointer to your delegate:
// On Windows, a C# delegate passed to native code defaults to the __stdcall calling convention,// but C and C++ function pointers default to __cdecl.// Define a macro so the function pointer type and the exported function use a matching convention on every platform.// A mismatch crashes the 32-bit Windows Player.// Check the target platform (_WIN32), not the compiler, because every Windows compiler// (MSVC, MinGW, and Clang) supports __stdcall.#if defined(_WIN32)#define STDCALL __stdcall#else#define STDCALL#endiftypedef void (STDCALL *MyFuncType)();MyFuncType registeredCallback;extern "C"{ void STDCALL RegisterMyCallback(MyFuncType func) { registeredCallback = func; }}
Your unmanaged code can invoke the callback immediately, or store the function pointer and invoke it later:
if (registeredCallback){ registeredCallback();}