跳转至

Delegate Marshalling

向非托管代码封送委托的原理。下面这些也类似:

  • 使用 xLua 在 C# 中创建一个 Lua 函数的委托。
  • 使用 HybridCLR 在 AOT 代码中创建一个热更方法的委托。
  • ...

反过来封送的原理也都类似。

Unmanaged Callers Only

使这个静态方法只能被非托管代码调用。取地址以后直接拿到一个非托管函数指针。

Unmanaged Function Pointer

  • Unity AOT 下,会为被标记的委托类型生成专门的 delegatePInvokeWrapperFunction(一个托管方法,在里面调用被包装的非托管函数指针),用于 Marshal.GetDelegateForFunctionPointer。

Mono PInvoke Callback

  • AOT 模式下使用。
  • 只能静态方法。
  • Unity 2022.3 里,如果方法是泛型方法不会生成代码。应该是个 bug。
  • 在非泛型方法上标记多次,只有最后一个会被使用,生成一次代码。
  • 生成的桥接函数的 Calling Convention 依赖于 MonoPInvokeCallback 参数里的委托类型。默认是 Platform Default Calling Convention。如果要修改的话,需要在委托上加 UnmanagedFunctionPointer,然后在参数里指定。
  • 生成的桥接函数的代码不依赖 MonoPInvokeCallback 参数里的委托。
  • 生成的函数以 ReversePInvokeWrapper 开头。

Get Function Pointer For Delegate

  • JIT 下,生成的桥接函数的代码依赖于参数里的委托,静态方法和实例方法都支持。之后需要保证该委托不被 GC 回收。使用 GCHandle.Alloc(object) 创建一个该委托的 Normal GCHandle 就能防止它被 GC。
  • Unity AOT 下,依赖 MonoPInvokeCallback 生成的代码。只能用于静态方法。不依赖参数里的委托。委托被 GC 了也没关系。

Get Delegate For Function Pointer

  • Unity AOT 下,委托类型上需要有 UnmanagedFunctionPointer。这样才会提前生成 delegatePInvokeWrapperFunction。