Unityでアプリを作る時にネイティブの機能を使いたい場合に、どうやったらいいのか調べた。Objective-Cでプラグインを作って、C#から呼び出してやることでできる。
Android編はこちら
C# からObjective-Cコードの呼び出し
- C#側で
[DllImport(__Internal)]
アノテーションでstatic extern
すると、普通のメソッドのように呼び出せる:
using System.Runtime.InteropServices;
public class HogeClass { [DllImport("__Internal")] private static extern void hogeNative();
public void Hoge() { hogeNative(); } }
|
- Unityプロジェクト内のAssets/Plugins/iOS以下にObjective-Cのソース(.m または .mm)を配置し、Cリンケージで関数を定義する
extern "C" { void hogeNative() { NSLog(@"hogeNative called"); } }
|
- BuildするとObjective-Cのソースがリンクされ、C#から呼び出すことができる
- 呼び出されるネイティブコードはObjective-CというかCです
- スタティックライブラリ(.a)を作って組み込んでもよい
- 受け渡せる引数や戻り値の型は、intやstringなど
Objective-CからC#にコールバックを呼び出す
ネイティブ側でイベント駆動や非同期処理など行わせる場合、なにか起こった時にObjective-CからC#のメソッドを呼び出してもらいたい(コールバック)。そのためにC#のメソッドをObjective-Cに渡して、呼び出せるような機構が必要。
- C#の
delegate
でコールバックの関数の型を宣言し、その呼び出される関数をAOT.MonoPInvokeCallbackAttribute
とやらでアノテートしたメソッドとして定義し、ネイティブに渡す:
using System.Runtime.InteropServices; using UnityEngine;
public class HogeClass { private delegate void HogeCallbackDelegate();
[DllImport("__Internal")] private static extern int hogeNative(HogeCallbackDelegate callback);
public void Hoge() { hogeNative(HogeCallback); }
[AOT.MonoPInvokeCallbackAttribute(typeof(HogeCallbackDelegate))] static void HogeCallback() { Debug.Log("HogeCallback called"); } }
|
- C(Objective-C)側でも同じ型のコールバック関数を
typedef
などで定義してやって、それを引数とする関数を作ってやる。呼び出しもそのまま行えばOK:
extern "C" { typedef void (*HogeCallbackDelegate)(); void hogeNative(HogeCallbackDelegate callback) { NSLog(@"hogeNative called"); callback(); } }
|
- Unity5.5.2p1で試したところ、Scripting BackendがMono2xだと(IL2CPPじゃないと)ビルドに失敗する
- コールバックに渡せるのは
static
メソッドだけなのでインスタンスを受け渡したいんだけど、手段がまだわかってない…(MarshalDirectiveException
が発生する)
参考