iOS與unity交互混編, 閉包方式實(shí)現(xiàn)互相調(diào)用

背景

unity需要調(diào)用其沒(méi)有實(shí)現(xiàn)的原生功能崇猫。
unity使用C#開(kāi)發(fā),可以與c++混編匾委。
iOS使用Objective-c開(kāi)發(fā)拖叙,可以與C++和C混編。
例如:

  • 支付赂乐,分享薯鳍,音視頻,但只提供了 iOS 平臺(tái) SDK挨措。
  • 優(yōu)秀插件
  • 需要通過(guò) Objective-C 調(diào)用 iOS 原生類庫(kù)代碼挖滤。

交互方式

Unity 通過(guò) C 與 iOS 進(jìn)行交互。
Unity 不能直接調(diào)用 C++ 的原因是 C++ 編譯會(huì)有 Name mangling 問(wèn)題运嗜。
Objective-C 可以與 C/C++ 進(jìn)行混編壶辜。使用 C 代碼封裝對(duì)應(yīng)的 Objective-C 代碼,提供給 Unity 使用担租。

unity主動(dòng)調(diào)用鏈:unity(C#) -> C -> iOS(Objective-C)
iOS調(diào)用鏈: unity(C#) -> 注冊(cè)回調(diào)到iOS -> iOS(Objective-C) -> 通過(guò)注冊(cè)的回調(diào)砸民,調(diào)用C -> 調(diào)用unity(C#)

注意:建議 C 函數(shù)名加有特定意義的前綴,避免函數(shù)名沖突。

unity交互部分

核心文件上代碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;  // 必須導(dǎo)入
using System

public class MonoPInvokeCallbackAttribute : Attribute   // 用于定義C語(yǔ)音回調(diào)的類
{
    public MonoPInvokeCallbackAttribute(Type type)
    {

    }
}

public class BridgeUnityToNative   // 定義了一個(gè)類岭参,用以做橋反惕,可自定義
{
    protected static BridgeUnityToNative _manager = null;
    public static BridgeUnityToNative Instance
    {
        get
        {
            if(_manager == null)
            {
                _manager = new BridgeUnityToNative();
            }
            return _manager;
        }
    }

    public delegate void CallBack(int res);  // 定義回調(diào),如果定義的方法需要有回調(diào)演侯,則必須先定義delegate姿染,才能核心交互代碼中使用
    
    // 核心交互代碼
    #if UNITY_IOS
    [DllImport("__Internal")]  // 固定形式,注冊(cè)TestCallback方法為可調(diào)用的C函數(shù)
    private static extern void TestCallback();  // 封裝必須為private, extern需要定義的方法,不然會(huì)報(bào)錯(cuò)


    [DllImport("__Internal")]
    private static extern void RegistCallback(CallBack callBack);  // 封裝必須為private, extern需要定義的方法,不然會(huì)報(bào)錯(cuò)

    [AOT.MonoPInvokeCallback(typeof(CallBack))]  // 將LogCallback方法秒际,注冊(cè)為回調(diào)
    static void LogCallback(int res)
    {
        Debug.Log("調(diào)用了c# callback" + res);
    }

    public void TestCallbackFunc(int retCode)  // 對(duì)外接口方法悬赏,,外部文件調(diào)用此方法驗(yàn)證demo
    {
        Debug.Log("調(diào)用了TestCallbackFunc" + retCode);
        TestCallback();
        RegistCallback(BridgeUnityToNative.LogCallback);
    }
    #endif
}

上述代碼娄徊,一共定義了兩個(gè)交互函數(shù)闽颇。
無(wú)回調(diào)方法TestCallback 和 有回調(diào)方法RegistCallback
由于作用域的問(wèn)題,兩個(gè)方法都只能private寄锐。所以對(duì)外接口需要用c#包一層

[AOT.MonoPInvokeCallback(typeof(CallBack))] 的下一個(gè)函數(shù)兵多,可以用于回調(diào)代理。其函數(shù)類類型必須與代理完全一致橄仆,否則會(huì)報(bào)錯(cuò)
這里函數(shù)名和回調(diào)類型剩膘,必須要跟iOS(Objective-C)的類型完全一致。不然會(huì)報(bào)錯(cuò)盆顾,無(wú)法調(diào)用整個(gè)函數(shù)怠褐。

注意事項(xiàng):TestCallback和'RegistCallback'方法。只在此處extern了方法名椎扬,所以不會(huì)有任何檢查機(jī)制惫搏,C#或iOS改了方法具温,對(duì)方完全察覺(jué)不到蚕涤,驗(yàn)證也很費(fèi)勁。所以精心維護(hù)一份交互文檔是很重要的铣猩。

iOS交互部分

因?yàn)橐霤++ , 所有.m文件的后綴要改成.mm
.h文件:

//
//  IOSToUnity.h
//  Unity-iPhone
//
//  Created by yangda on 2019/1/12.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#ifndef ConnectUnityToiOS_h
#define ConnectUnityToiOS_h
#endif /* ConnectUnityToiOS_h */

@interface ConnectUnityToiOS : NSObject

typedef void(*CallBack)(int retCode);

+ (ConnectUnityToiOS *)sharedInstance;

extern "C"
{
    void TestCallback();
    
    void RegistCallback(CallBack callBack);
}

@end

其中:typedef void(*CallBack)(int retCode);對(duì)應(yīng)C#代碼中的代理public delegate void CallBack(int res);定義
核心代碼為:

extern "C"
{
    void TestCallback();
    
    void RegistCallback(CallBack callBack);
}

extern "C"可以擴(kuò)展C函數(shù)揖铜,用于交互

.m文件:

//
//  IOSToUnity.m
//  Unity-iPhone
//
//  Created by yangda on 2019/1/12.
//

#import "ConnectUnityToiOS.h"

@interface ConnectUnityToiOS()

@property(atomic, assign)CallBack callBack;

@end


@implementation ConnectUnityToiOS
// MARK:- OC部分
static ConnectUnityToiOS *instance = nil;
+ (ConnectUnityToiOS *)sharedInstance{
    @synchronized(self) {
        if(instance == nil) {
            instance = [[[self class] alloc] init];
        }
    }
    return instance;
}

- (void)registTestCallBack:(CallBack)callBack {
    _callBack = callBack;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        _callBack(1);
        NSLog(@"iOS registTestCallBack");
    });
}

// MARK:- C++部分
void TestCallback()
{
    NSLog(@"TestCallback");
}

void RegistCallback(CallBack callBack)
{
    NSLog(@"iOS RegistCallback");
    [ConnectUnityToiOS.sharedInstance registTestCallBack:callBack];
}


@end

如果有錯(cuò)誤的地方歡迎指正

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市达皿,隨后出現(xiàn)的幾起案子天吓,更是在濱河造成了極大的恐慌,老刑警劉巖峦椰,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龄寞,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡汤功,警方通過(guò)查閱死者的電腦和手機(jī)物邑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人色解,你說(shuō)我怎么就攤上這事茂嗓。” “怎么了科阎?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵述吸,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我锣笨,道長(zhǎng)蝌矛,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任错英,我火速辦了婚禮朴读,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘走趋。我一直安慰自己衅金,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布簿煌。 她就那樣靜靜地躺著氮唯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪姨伟。 梳的紋絲不亂的頭發(fā)上惩琉,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音夺荒,去河邊找鬼瞒渠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛技扼,可吹牛的內(nèi)容都是我干的伍玖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼剿吻,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼窍箍!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起丽旅,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤椰棘,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后榄笙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體邪狞,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年茅撞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了帆卓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杆逗。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鳞疲,靈堂內(nèi)的尸體忽然破棺而出罪郊,到底是詐尸還是另有隱情,我是刑警寧澤尚洽,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布悔橄,位于F島的核電站,受9級(jí)特大地震影響腺毫,放射性物質(zhì)發(fā)生泄漏癣疟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一潮酒、第九天 我趴在偏房一處隱蔽的房頂上張望睛挚。 院中可真熱鬧,春花似錦急黎、人聲如沸扎狱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)淤击。三九已至,卻和暖如春故源,著一層夾襖步出監(jiān)牢的瞬間污抬,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工绳军, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留印机,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓门驾,卻偏偏與公主長(zhǎng)得像射赛,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猎唁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354