Swift だけで作った Native Plugin で Unity にコールバックする
- Swift だけで、Unity の iOS の Native Plugin を作る方法を紹介しました
- Swift から Unity へコールバックしたい場合がよくあります
- 例えば、Bluetoothを使えるようにするアセットで、検出した BLEデバイスを Unity へ通知する事が可能です
- Unity から Native に関数のポンタを渡しておきます
- iOS では、受け取った関数のポインタを実行します
今回のサンプル
- リポジトリはこちらです
- [Swift だけで、Unity の iOS の Native Plugin を作る](Swift だけで、Unity の iOS の Native Plugin を作る方法) の内容を前提知識にしています
- 今回は、文字列一つを Swift から Unity へ渡すコールバックを実装します
処理の流れ
- Unity で実行されるコールバックの型と関数を用意する
- 関数のポインタを渡して、コールバックを登録する関数を実装する
- 実際に呼び出される関数を実装する
- コールバックを登録する関数を呼び出す
== ここまで C# ここから Swift === - コールバックを登録する関数を実装する
- 受け取った関数のポインタを実行する
Unity の実装
最終目標
- Swift で作成された任意の文字列で、
swiftPmPlugin_callBackAction
が実行されることを目指します
private static event Action<string> swiftPmPlugin_callBackAction;
Unity で実行されるコールバックの型と関数を用意する
- コールバックされる関数の型を決めます
- 文字列の引数1つだけです
- 定義には、UnmanagedFunctionPointer を付けます
- 引数には、MarshalAs を付けます
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void swiftPmPlugin_callBackType([MarshalAs(UnmanagedType.LPStr), In] string message);
関数のポインタを渡して、コールバックを登録する関数
- 関数のポインタを引数に持つ関数です
- 関数のポインタの引数には、
[MarshalAs(UnmanagedType.FunctionPtr)]
を付けます
[DllImport("__Internal")]
private static extern void swiftPmPlugin_callBack([MarshalAs(UnmanagedType.FunctionPtr)] swiftPmPlugin_callBackType callback);
Swift から呼び出される関数
-
MonoPInvokeCallback
を付けて、作成したコールバックの型の関数を実装します - 最終目標である
swiftPmPlugin_callBackAction
を実行します
[MonoPInvokeCallback(typeof(swiftPmPlugin_callBackType))]
private static void swiftPmPlugin_callBackHandler(string message)
{
swiftPmPlugin_callBackAction(message);
}
コールバックを登録する
- Swift から受け取った文字列の処理を
swiftPmPlugin_callBackAction
に実装します
swiftPmPlugin_callBackAction = (string message) =>
{
Debug.Log("native message -> " + message);
};
- コールバックを登録します
swiftPmPlugin_callBack(swiftPmPlugin_callBackHandler);
Swift の実装
C# (c) の呼び出し口を作る
-
@_cdecl
を付けて Swift で関数を定義します - コールバックは、C言語で定義されるので、
@convention(c)
を付けます - Swift.String から一度、NSString へ変換して、
UnsafePointer<CChar>
を取得します
@_cdecl("swiftPmPlugin_callBack")
public func swiftPmPlugin_callBack(_ handler: @convention(c) (UnsafePointer<CChar>) -> Void) {
let str = "this is swift string"
let nsStr = str as NSString
handler(nsStr.utf8String!)
}
Framework の出力と設定
- こちらの記事の
Framework でビルドする
の章以降と同じ手順で実行ビルド可能です
-
swiftPmPlugin_callBack
を実行したときに、swiftPmPlugin_callBackAction
の内容が実行されている事を確認します
おわりに
- Swift が C言語と親和性が高く、Unity と Swift のやりとりは、コールバックなどを含めて比較的容易に実装が可能です
- Objective-C を挟まなくても大概のことはできそうだと思っています
- また、Cのインタフェースを揃えて、事前に Framework 化すると、Swift 実装の場合でも、PostProcess が不要となるので、Swift での Native Plugin が実装しやすいです
- Swift から Unity コールバックするのは、応用の幅が広いので、活用して行きたいです