ユニバーサル Windowsプラットフォーム: IL2CPP スクリプトバックエンドを使用して生成したプロジェクト
ユニバーサル Windows プラットフォーム: IL2CPP スクリプティングバックエンドのデバッグ

ユニバーサル Windows プラットフォーム: IL2CPP スクリプティングバックエンドのプラグイン

The plugin model for Universal Windows Platform is similar to other Unity platforms (such as Windows standalone).

マネージプラグイン

By default, IL2CPP targets .NET 2.0 API compatiblity level. That means it does not support managed plugins targeting .NET 4.5 or consuming any of Windows Runtime APIs. All managed plugins must be targeting .NET 4.5 or equivalent API when using this compatiblity level. You can switch to .NET 4.6 API compatibilty level in Player settings if you wish to lift these restrictions.

Note The .Net 3.5 scripting runtime is deprecated, but it will be available for Unity 2018.3 and 2018.4 LTS. Please migrate or start new Projects with the .NET 4.x runtime.

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 targetting different .NET API for Universal Windows Platform.

ネイティブプラグイン

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
  • Currency
  • SAFEARRAY
  • IDispatch
  • TBStr
  • VBByRefStr

x86 での P/Invoke 関数のデフォルトの呼び出し規約は __stdcall です。

ネイティブプラグインは、2 通りの方法で作成することができます。precompiled DLL と C++ ソースコードです。

プリコンパイルしたネイティブプラグイン

ランタイムで DLL を読み込み、関数のエントリーポイントを見つけ、呼び出すことによって、プリコンパイルしたネイティブプラグインを P/Invoke 呼び出しできます。これらの DLL は、ターゲットにする CPU アーキテクチャ用の適切な Windows SDK に対してコンパイルする必要があります。また、DLL は、Unity プロジェクトに追加するとき Plugin インスペクター上でも設定しなければいけません。

C++ ソースコードのネイティブプラグイン

C++ (.cpp) コードファイルは Unity プロジェクトに直接加えることができ、Plugin インスペクターでプラグインとして動作します。これらのC++ ファイルがユニバーサル Windows プラットフォーム、および IL2CPP スクリプティングバックエンドと互換性があるように設定されている場合は、マネージアセンブリから生成される C++ コードと共にコンパイルされます。

関数は生成された C++ コードと一緒にリンクされるので、P/Invoke を行う DLL はありません。このため、DLL の名前の代わりに Internal キーワードを使用することができます。これにより、 Internal キーワードは、関数をランタイムに読み込む代わりに、C++ リンカーに関数を解決させます。

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

呼び出しはリンカーによって解決されるので、マネージドサイドで関数の宣言のエラーが発生すると、ランタイムのエラーではなくリンカーのエラーが発生します。これはまた、動的な読み込みがランタイム時に行われる必要がないことを意味し、関数は直接呼び出されます。これによって、P/Invoke 呼び出しのオーバーヘッドは著しく減少します。

P/Invoke の制限

ユニバーサル Windows プラットフォームでは、IL2CPP スクリプティングバックエンドを使用するときに dll 名(kernelbase.dll など) を指定して、特定のシステムライブラリに P/Invoke を行うことはできません。 プロジェクトの外部に存在する DLL に P/Invoke を行なおうとすると、実行時に DllNotFoundException が発生します。

ただし、 DLL の名前の代わりに **Internal キーワードを指定して、システム関数に P/Invoke を行うことは可能です。これにより、リンカーがビルド時に関数を解決します。

参考資料

Plugin インスペクター


ユニバーサル Windowsプラットフォーム: IL2CPP スクリプトバックエンドを使用して生成したプロジェクト
ユニバーサル Windows プラットフォーム: IL2CPP スクリプティングバックエンドのデバッグ