【序文】
前 2 回の記事では、Unity と iOS の相互作用の原理を詳しく紹介しましたが、よく読んでいただければ、基本的には理解できると思います (もちろん、理解するまでに数時間かかる場合もあります)。ここでは、一般的な対話型コードの例を直接示します。
【基本的なやりとり】
基本的なデータ型と文字列型を渡す
public class Sample : MonoBehaviour
{
[DllImport("__Internal")]
static extern void PassIntAndString (int a, string b);
}
extern "C" void PassIntAndString(int a,const char* b)
{
NSLog(@"a = %d", a);
NSString *str = [NSString stringWithUTF8String:b];
NSLog(@"%@", str);
}
プリミティブデータ型の配列を渡す
写真のデータなど、転送するデータが大量になる場合がありますが、このとき配列が使用されることがあります。
public class Sample : MonoBehaviour
{
[DllImport("__Internal")]
private static extern void SendImageData (int length, int[] data);
}
extern "C" void SendImageData(int length,int* data)
{
for (int i = 0; i < length; i++) {
NSLog(@"imagedata %d : %d", i, data[i]);
}
}
OC が MonoPInvoke を通じて C# 関数を直接コールバックできるようにします。
一般に、コールバック関数であっても、UnitySendMessage を使用して OC を実装し、C# を呼び出します。もちろん、変換を見つける場合、UnitySendMessage は遅くなります。パフォーマンス要件がある場合は、PInvoke を使用してコールバックを実装する必要があります。UnitySendMessage を使用する場合はスレッド セーフですが、PInvoke を使用する場合はスレッド セーフを維持する必要があります。
public class Sample:MonoBehaviour
{
//回调参数必须有MonoPInvokeCallBack,而且是static的
[MonoPInvokeCallback(typeof(CallBack))]
public static int PassCallBack(string url) {
}
[DllImport("__Internal")]
private static extern void SetCallBack(CallBack cb );
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int CallBack(string url);
private void Set ()
{
SetCallBack (PassCallBack);//直接把函数指针传递过去
}
}
#if defined(__cplusplus)
extern "C"
{
#endif
// C#设置过来的函数指针类型
typedef int (*PassCallBack)(const char*);
static PassCallBack callBack;
void SetCallBack(PassCallBack cb) {
callBack = cb;
}
#if defined(__cplusplus)
}
#endif
void SetUrl(const char* url) {//回调
if (callBack != nil) {
callBack(url);
}
}
OC は基本データ型の配列を C# に渡します
public class Sample:MonoBehaviour
{
//回调参数必须有MonoPInvokeCallBack,而且是static的
[MonoPInvokeCallback(typeof(CallBack))]
public static int PassCallBack(int length,IntPtr data) {
byte[] buffer = new byte[length];
Marshal.Copy(data, buffer, 0, length);//将数据拷贝出来
}
[DllImport("__Internal")]
private static extern void SetCallBack(CallBack cb);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int CallBack(int length,IntPtr data);
private void Set ()
{
SetCallBack (PassCallBack);//直接把函数指针传递过去
}
}
#if defined(__cplusplus)
extern "C"
{
#endif
// C#设置过来的函数指针类型
typedef int (*PassCallBack)(int,void*);
static PassCallBack callBack;
void SetCallBack(PassCallBack cb) {
callBack = cb;
}
#if defined(__cplusplus)
}
#endif
void SendData(int length) {//回调
NSMutableArray *mutableArray = [NSMutableArray array];
NSArray *array = [NSArray arrayWithArray:mutableArray];
if (callBack != nil) {
callBack(length,array);
}
}
C# オブジェクトを渡す
オブジェクトを転送するには 2 つの方法があり、1 つはオブジェクトを配列にシリアル化する方法 (ここでは説明しませんが、基本データ型の配列を渡すのと同じです) から、オブジェクトを逆シリアル化して復元します。もう 1 つは、オブジェクトを渡す方法です。 Pass 関数ポインタと同様のオブジェクト ポインタ アウト。
オブジェクトポインタの受け渡し
using System.Runtime.InteropServices;
public class Sample {
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CallBack(IntPtr objectPtr);
[DllImport("__Internal")]
private static extern void PassObject(IntPtr objectPtr, CallBack callback);
[MonoPInvokeCallback(typeof(CallBack))]
private static void GetObject(IntPtr objectPtr) {
GCHandle handle = (GCHandle) objectPtr;
//从指针读取TestObjet
TestObjet test = handle.Target as TestObjet;
handle.Free ();
}
private static void Set() {
TestObject test = new TestObject();
IntPtr objectPtr = (IntPtr)GCHandle.Alloc (TestObject);
PassObject (objectPtr, GetObject);
}
}
public class TestObjet
{
public int a;
public bool b;
}
[複雑な相互作用]
2 つのインターフェイス ジャンプは実際には表示画面を置き換えるためのもので、iOS 上の画面表示は UIWindow にあり、UIWindow の rootViewController を変更するだけです。
Unity をライブラリとして Android または iOS に統合する
【参考】
Unity3D と iOS 間の相互作用 - プログラマーが求めた
iOS および Unity メッセージング (Swift および C#) - ショート ブック (jianshu.com)