Version: 5.4
Windows ストア: IL2CPP スクリプトバックエンドで生成したプロジェクト
Windows Store Apps: IL2CPP スクリプティングバックエンドのデバッグ

Windows ストア: IL2CPPスクリプトバックエンドでプラグイン

現時点では、 IL2CPP スクリプトバックエンドによる Windows Store 向けのプラグイン方式は、 .NET よりはむしろ Unity の他のプラットホーム (Windows スタンドアローン版など) とよく似ています。

マネージドプラグイン

.NET スクリプトバックエンドと違って、IL2CPP スクリプトバックエンドは、.NET 4.5 やWindows Runtime API を対象としたマネージドプラグインをサポートしません。すべてのマネージドプラグインは、.NET 3.5 か 同等の API を対象とする必要があります。

.NET スクリプトバックエンドと比べてもう1つの違いは、スクリプトバックエンドでの IL2CPP 設定は、Unity エディターかスタンドアロンプレイヤーとしてまったく同じ.NET API サーフェイスの影響を受けることです。したがって、Windows ストア用の異なる.NET API の別々の対象バージョンをコンパイルする必要性がなく、同じプラグインを使用することができます。

ネイティブプラグイン

スクリプトバックエンドでの 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

x86 での P/Invoke 関数用デフォルトのコーリングコンベンションは、**stdcallです。

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

Precompiled ネイティブプラグイン

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

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

Unity プロジェクトに直接 C++ (.cpp) コードファイルを追加することが可能です。それは、プラグインインスペクターでプラグインとして動作します。Windows Store やスクリプトバックエンド上の IL2CPP と互換性があるように設定された場合、これらの C++ ファイルはマネージド・アセンブリから生成されて取得した C++ コードと一緒にコンパイラされます。

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

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

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

P/Invoke の制限

Windows Store では、スクリプトバックエンドで IL2CPP を設定する場合、dll の名前(kernelbase.dll のような)を指定することで特定のシステムライブラリに P/Invoke することはできません。プロジェクトの外部に存在する DLL に P/Invoke を試みることでランタイム時 DllNotFoundException になります。

しかし、ビルド時に関数を解決するリンカになる DLL 名に代わって、「**Internal」のキーワードを指定することで、まだこれらのシステム関数に P/Invoke することが可能です。

参照

Plugin インスペクター

Windows ストア: IL2CPP スクリプトバックエンドで生成したプロジェクト
Windows Store Apps: IL2CPP スクリプティングバックエンドのデバッグ