テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

NativePluginsにC#デリゲートを登録する

NativePluginsからUnityへメッセージを送る際、コールバックやSendMessageを使うのだが、実はもう一つだけ方法がある。この方法はC#のデリゲートをコールバックとしてネイティブに登録し、それを直接呼び出してもらう方法だ。


スクリーンショット 2014-03-26 6.53.54
これを実現するには、MonoPInvokeCallbackAttributeを使用する。この属性を宣言したメソッドは、ネイティブプラグイン側にデリゲート(関数ポインタ)として受け渡しすることが出来る。なお、受け渡しが可能なのはstaticメソッドのみなので、インスタンスからこの処理を使用する場合は一旦マネージャクラスを通すような実装にするのが良さそうだ。

C#

    //実際の使い方
    public static void CallPlugin ()
    {
        _CallPlugin (CallbackResult);
    }

    //ネイティブにメソッドを受け渡す
    [DllImport("__Internal")]
    private static extern void _CallPlugin (Callback method);

    //登録するメソッドと同じフォーマットのデリゲート
    public delegate void Callback ();

    //登録するメソッドにはMonoPInvokeCallbackAttributeを付ける
    [AOT.MonoPInvokeCallbackAttribute(typeof(Callback))]
    static void CallbackResult ()
    {
        // call back
    }

C側

extern "C" typedef void (*MyCallback)();

extern "C" {

    void _CallPlugin(MyCallback callback)
    {
        (callback)();
    }
}

他のWebViewや他のviewからのコールバックとして受けて、そのままunityのGameObject生成みたいな事をすると、別スレッドからのアクセス扱いになりそうな気がする(多分SendMessageが次フレームに届くのはメインループ待ってるのが理由)。