查看原文
其他

Unity3D Native 插件开发: IL2CPP 机制篇

2016-05-23 AEONME Gad-腾讯游戏开发者平台
这篇文章的目的,主要是介绍 Unity中,C# 代码是如何调用 C 语言代码,包括内部的实现机制和原理
写在最前
Unity 4.0 使用的是 mono dl 机制来实现 C# 到 C 语言的调用,简单来说是如下的模式:
注册 C 语言函数名称(mono_dl_register_symbol)mono_dl_open、mono_dl_symbol、mono_dl_close 来实现函数调用
需要说说明的是,不同于系统的dlopen、dlsym、dlclose函数是用来调用动态库(.so),mono调用的实际上是静态机器码
Unity 5 对底层机制进行了一次革新,这篇文章主要基于 Unity 5.x 版本进行说明
基础知识
IL2CPP, 是将中间语言转换成C++语言的一种技术,执行过程如下:
Unity 脚本(C#、JavaScript)编译成中间语言(IL,动态库等)

利用IL2CPP程序,将IL转换成C++语言与之前不同,编译到 XCode 之后不再包含动态库(.dll)文件理论上讲,直接用C++编译运行机器码,要比 mono 运行环境代码快许多,不得不说 Unity 为了性能也是够拼了
代码分析
在利用前一节的示例功能,在XCode工程中找到char* IOS_GetUUID()
函数位置并断点在入口处,运行程序后分析调用堆栈:
找到调用函数如下
可以看到这个函数已经完整可以看出Unity的处理模式了:
1、定义一个无参数,返回值为 char* 的函数方法typedef char* (DEFAULT_CALL *PInvokeFunc) ();
2、把我们编写的函数进行类型转换_il2cpp_pinvoke_func = (PInvokeFunc)IOS_GetUUID;
3、调用函数,并获取返回值char* _return_value = _il2cpp_pinvoke_func();
4、将结果保存到 C# 内部使用的结构__return_value_unmarshaled = il2cpp_codegen_marshal_string_result(_return_value);
5、释放函数返回的 char* 指针il2cpp_codegen_marshal_free(_return_value);注意:到这里对内存进行了释放,那么在我们实现的函数结构体内不用担心内存泄露了
再深入一步,在同一个文件cpp中,可以找到下面的一些方法
包含了 C# 中 UUID 类的完整定义
另外,我在本次使用的测试脚本代码如下:
所以,整个运行机制的轮廓就大致清楚了,正如前文 IL2CPP 描述的那样,C# 代码最终都被转换成了 C++ 代码

多说两句我们知道,Unity 游戏最终其实运行在虚拟机中,这次 Unity 5 把虚拟机也变成了现在的 IL2CPP 模式的虚拟机,最终效率如何还不得而知
阅读推荐:Unity开发秘诀丨U3D调用Native代码的原理解析Unity性能优化专题---腾讯牛人分享经验
腾讯游戏开发者平台长按,识别二维码,加关注
经验分享丨项目实践项目孵化丨渠道发行做有梦想的游戏人-GAME AND DREAM-

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存