找回密码
 立即注册
查看: 253|回复: 0

Unity 中IOS平台 C#怎么和OC通信?

[复制链接]
发表于 2022-9-22 13:48 | 显示全部楼层 |阅读模式
1、C# 调用 OC的接口
首先在C# 中声明OC 中定义的接口,如下所示
public class SDKForIOS : MonoBehaviour
{

    [DllImport("__Internal")]
    private static extern void SDKInit(); // 此接口在mm文件中定义

   
    public  void Start()
    {
        SDKInit();
    }
}

DllImport 其功能是提供从非托管DLL导出的函数的必要调用信息,DllImport属性应用于方法,要求最少要提供包含入口点的dll的名称。要不然调用不成功哦!!!
然后看OC中怎么定义的?

在头文件 SDKIOS.h 中定义
//用于Unity的调用(Unity只能调用C的方法,调不到OC的方法)
#if defined(__cplusplus)
extern "C"
{
#endif

    extern void SDKInit();

#if defined(__cplusplus)
}
#endif
在源文件 SDKIOS.mm 中定义
void OnSDKInit()
{
    NSLog(@"hello world!");
}
extern "C"会指示编译器这部分代码按C语言的方式进行编译,因为il2cpp后的代码都是按C语言的方式编译的,所以我们这里也要这样定义,要不调用会失败哦!!!
按照上面的方式我们启动游戏后就能看到打印"hello world!" 了。
<hr/>2、OC怎么调用C#代码呢?
OC调用C#代码有两种调用方式
第一种方式:
如果对Unity有些了解的同学肯定都知道一个接口,就是 UnitySendMessage ,然后传入组件的名字和方法的名字就可以调用了。
这种调用方式是线程安全的,但是可能会相对耗时一些,它的实现会遍历所有的transfrom然后找到相应的组件及方法进行调用。

第二种方式:
public class SDKIOS : MonoBehaviour
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void callbackN0Delegate(IntPtr data);
    [DllImport("__Internal")]
    public static extern void SetN0CallBack(IntPtr callback);
   
    [DllImport("__Internal")]
    private static  extern void OnSDKInit();
    // Start is called before the first frame update
    void Start()
    {
        RegisterCallback();
        OnSDKInit();
    }

    private void RegisterCallback()
    {
        callbackN0Delegate callbackN0_delegate = SendDataToGame;

        //将Delegate转换为非托管的函数指针
        IntPtr intptrN0_delegate = Marshal.GetFunctionPointerForDelegate(callbackN0_delegate);

        //调用非托管函数
        SetN0CallBack(intptrN0_delegate);
    }

    //原生层发送数据到游戏层
    [MonoPInvokeCallback(typeof(callbackN0Delegate))]
    static void SendDataToGame(IntPtr data)
    {
        var dataStr = Marshal.PtrToStringAnsi(data);
        Debug.Log(dataStr);
    }

}

如代码所示,一开始定义了委托函数  public delegate void callbackN0Delegate(IntPtr data);  IntPtr类似于C++中的指针,用于和原生代码通信

[DllImport("__Internal")]
public static extern void SetN0CallBack(IntPtr callback);
这行代码代表原生层定义了SetN0CallBack 接口,用于回调SendDataToGame

RegisterCallback 函数目的是将委托函数SendDataToGame 通过SetN0CallBack 接口注册到原生层。
注意:[MonoPInvokeCallback(typeof(callbackN0Delegate))] 标签必须加,否则执行时会报错!!
接下来我们看下OC层是怎么定义的?
#if defined(__cplusplus)
extern "C"
{
#endif

    extern void OnSDKInit();


    typedef void(*CALLBACK_N0)(const char*);  //定义函数指针
    static CALLBACK_N0 callback_n0 = nil;     //定义函数指针对象
    void SetN0CallBack(CALLBACK_N0 callback);   

#if defined(__cplusplus)
}
#endif

void OnSDKInit()
{
    NSLog(@"OnSDKInit");
    if(callback_n0 != nil)
    {
        callback_n0("call back ok!!!");  //这里将”call back ok!!!“字符串发给C#层打印
    }
}

void SetN0CallBack(CALLBACK_N0 callback)
{
    callback_n0 = callback;
}
OC层代码很简单这里不做过多解释。
相比两种方式,第二种调用方式较第一种调用方式更加高效,但不是线程安全的,如果需要线程安全的则要再加额外的代码。
好了,C#和OC 之间的通信到这里就写完了,

那Android平台 java又是如何和C#通信的呢?且听下回分解
阿文:Unity 中Android平台 C#怎么和java通信?
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-7-4 09:11 , Processed in 0.092585 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表