기술 자료

Unity Engine

Unity Engine

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
AOT.MonoPInvokeCallbackAttribute
that indicates the matching delegate type.

Register a managed callback

The following C# example defines a delegate type and a static callback function, and passes the callback to the unmanaged
RegisterMyCallback
function:
using 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); }}
중요
When you pass a method to
RegisterMyCallback
, the runtime creates a delegate instance. The marshaller keeps that delegate alive only for the duration of the call, so a callback that native code invokes immediately is safe. If native code stores the function pointer to call later, as in this example, keep a managed reference to the delegate, such as in a static field, for as long as native code might call it. Otherwise, the garbage collector can collect the delegate, and a later callback uses an invalid function pointer, which crashes or corrupts your application.
참고
If you use a precompiled, dynamically linked library, change the
DllImport
value to the library name. Use the special string
__Internal
for source code plug-ins and statically linked libraries. For more information, refer to DllImport attribute.

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();}

Additional resources