|
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(&#34;__Internal&#34;)]
public static extern void SetN0CallBack(IntPtr callback);
[DllImport(&#34;__Internal&#34;)]
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(&#34;__Internal&#34;)]
public static extern void SetN0CallBack(IntPtr callback);
这行代码代表原生层定义了SetN0CallBack 接口,用于回调SendDataToGame
RegisterCallback 函数目的是将委托函数SendDataToGame 通过SetN0CallBack 接口注册到原生层。
注意:[MonoPInvokeCallback(typeof(callbackN0Delegate))] 标签必须加,否则执行时会报错!!
接下来我们看下OC层是怎么定义的?
#if defined(__cplusplus)
extern &#34;C&#34;
{
#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(@&#34;OnSDKInit&#34;);
if(callback_n0 != nil)
{
callback_n0(&#34;call back ok!!!&#34;); //这里将”call back ok!!!“字符串发给C#层打印
}
}
void SetN0CallBack(CALLBACK_N0 callback)
{
callback_n0 = callback;
}
OC层代码很简单这里不做过多解释。
相比两种方式,第二种调用方式较第一种调用方式更加高效,但不是线程安全的,如果需要线程安全的则要再加额外的代码。
好了,C#和OC 之间的通信到这里就写完了,
那Android平台 java又是如何和C#通信的呢?且听下回分解
阿文:Unity 中Android平台 C#怎么和java通信? |
|