Version: 5.6
Windows Store: Generated project with IL2CPP scripting backend
Windows Store Apps: Debugging on IL2CPP Scripting Backend

Windows Store: Plugins on IL2CPP Scripting Backend

At this point in time, the plugin model for Windows Store with IL2CPP scripting backend is much more similar to other Unity platforms (such as Windows standalone), rather than Windows Store with .NET scripting backend.

托管插件

Unlike .NET scripting backend, IL2CPP scripting backend does not support managed plugins targeting .NET 4.5 or any of Windows Runtime APIs. All managed plugins must be targeting .NET 3.5 or equivalent API.

Another difference compared to .NET scripting backend is that IL2CPP scripting backend exposes the exact same .NET API surface as Unity editor or standalone player, so it’s possible to use the same plugins without the need to compile separate versions target different .NET API for Windows Store.

原生插件

IL2CPP 脚本后端支持通过 P/Invoke 机制使用原生插件。也就是说,可通过指定原生函数原型再调用该函数来直接从 C# 代码调用原生插件。例如:

[DllImport("MyPlugin.dll")]
private static extern int CountLettersInString([MarshalAs(UnmanagedType.LPWSTR)]string str);

private void Start()
{
    Debug.Log(CountLettersInString("Hello, native plugin!"));
}

此类函数在 MyPlugin.dll 内的实现如下所示:

extern "C" __declspec(dllexport)
int **stdcall CountLettersInString(wchar_t* str)
{
    int length = 0;
    while (*str++ != nullptr)
        length++;
    return length;
}

P/Invoke 编组规则与官方 .NET 编组规则一致,但少数不受支持的类型除外:

  • AnsiBStr
  • BStr
  • Currency
  • SAFEARRAY
  • IDispatch
  • IUnknown
  • TBStr
  • VBByRefStr

The default calling convention for P/Invoke functions on x86 is **stdcall.

可通过两种方式编写原生插件:预编译的 DLL 或 C++ 源代码。

预编译的原生插件

对预编译的原生插件进行 P/Invoke 调用的工作原理是在运行时加载 DLL,找到函数入口点,然后调用它。必须针对目标 CPU 架构的适当 Windows SDK 编译这些 DLL。添加到 Unity 项目时,还必须在 Plugin Inspector 中配置这些 DLL。

C++ 源代码原生插件

It is possible to add C++ (.cpp) code files directly into Unity project, which will act as a plugin in Plugin Inspector. If configured to be compatible with Windows Store and IL2CPP scriping backend, these C++ files will be compiled together with C++ code that gets generated from managed assemblies:

由于函数与生成的 C++ 代码链接在一起,所以没有单独的 DLL 可进行 P/Invoke 调用。因此,可以使用“__Internal”关键字代替 DLL 名称,从而使 C++ 链接器负责解析函数,而不是在运行时加载函数:

[DllImport("__Internal")]
private static extern int CountLettersInString([MarshalAs(UnmanagedType.LPWSTR)]string str);

由于调用由链接器解析,因此在托管端的函数声明中发生错误将产生链接器错误,而不是运行时的错误。这也意味着,在运行时不需要进行动态加载,而直接调用函数。这种方式显著降低了 P/Invoke 调用的开销。

P/Invoke 限制

On Windows Store you cannot P/Invoke into specific system libraries by specifying the dll name (like “kernelbase.dll”) when using IL2CPP scripting backend. Attempting to P/Invoke into any DLL that exists outside of the project will result in DllNotFoundException at runtime.

但是,仍然可以通过指定“**Internal”关键字而不是 DLL 名称来对这些系统函数进行 P/Invoke 调用,这会使链接器在构建时解析函数。

另请参阅

Plugin Inspector

Windows Store: Generated project with IL2CPP scripting backend
Windows Store Apps: Debugging on IL2CPP Scripting Backend