导语

该系列将会分为以下几个部分:
1. 总览(本文)
2. c++代码解析
3. 调试c++代码
4. 方法调用(一般方法,虚方法等)
5. 泛型共享
6. 类型与方法的 P/invoke 封装
7. 垃圾回收
8. 测试框架与使用

什么是IL2CPP

IL2CPP 是 Unity 自 4.6.1p5版本 提出的一种新的 scripting backend 方式,为Unity提供了更加高效、更加便携的虚拟机,IL2CPP分为两个独立的部分:

  • AOT(静态编译)编译器
  • 运行时库

其中AOT编译器将 IL(由.Net编译器输出的中间语言)转换为C++源码,而运行时库则会提供诸如 垃圾回收、线程/文件获取(独立于平台,与平台无关)、内部调用直接修改托管数据结构的原生代码 的服务与抽象。

AOT编译器

所谓AOT编辑器即 il2cpp.exe
在 Windows 系统中你可以在 Editor\Data\il2cpp 目录中找到它,
在 OSX 系统中你可以在 Contents/Frameworks/il2cpp/build,即Unity的安装目录中找到它。
il2cpp.exe 是由C#编写的受托管的可执行程序,它接受我们在Unity中通过Mono编译器生成的托管程序集,并生成指定平台下的C++代码。

IL2CPP的工具链如下图所示:

il2cpp-toolchain

运行时库

IL2CPP技术的另一部分是运行时库(libil2cpp),它的存在是为了支持IL2CPP虚拟机的运行,运行时库几乎完全由C++代码编写,并作为一个静态库与最终的可执行程序链接。(值得一提的是,IL2CPP技术十分得益于使用了libil2cpp这一更轻便的运行时库)

你可以通过查看 libil2cpp 的头文件了解其的代码构成(Windows 系统下的目录为Editor\Data\PlaybackEngines\webglsupport\BuildTools\Libraries\libil2cpp\include,OSX 系统下的目录为 Contents/Frameworks/il2cpp/libil2cpp),例如你可以在 codegen/il2cpp-codegen.h 文件中看到 il2cpp.exe 生成C++代码的接口以及 运行时库 的接口。

运行时库的另一关键功能是提供了垃圾回收,这一块内容将在后续的文章里再详细探讨。

AOT编译器是如何运行的

让我们来看一个例子(该例子运行在 Windows 系统下 Unity 5.0.1版本中)
开启一个新的工程,将如下脚本添加至主相机上:

  1.  
    using UnityEngine;
  2.  
     
  3.  
    public class HelloWorld : MonoBehaviour
  4.  
    {
  5.  
    void Start ()
  6.  
    {
  7.  
    Debug.Log("Hello, IL2CPP!")
  8.  
    }
  9.  
    }

此时我们发布一个WebGL平台下的程序,并使用 Process Explorer 工具查看Unity通过什么命令行对 il2cpp.exe 进行了调用:

  1.  
    "C:\Program Files\Unity\Editor\Data\MonoBleedingEdge\bin\mono.exe"
  2.  
    "C:\Program Files\Unity\Editor\Data\il2cpp/il2cpp.exe"
  3.  
    --copy-level=None
  4.  
    --enable-generic-sharing
  5.  
    --enable-unity-event-support
  6.  
    --output-format=Compact
  7.  
    --extra-types.file="C:\Program Files\Unity\Editor\Data\il2cpp\il2cpp_default_extra_types.txt"
  8.  
    "C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\Managed\Assembly-CSharp.dll"
  9.  
    "C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\Managed\UnityEngine.UI.dll"
  10.  
    "C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\il2cppOutput"

这个命令行看起来又复杂又吓人,不用担心,让我们逐步来解析它,

"C:\Program Files\Unity\Editor\Data\MonoBleedingEdge\bin\mono.exe"

首先,Unity启动 mono.exe

  1.  
    "C:\Program Files\Unity\Editor\Data\il2cpp/il2cpp.exe
  2.  
     

接着启动 il2cpp.exe


剩下的命令行则是传递给 il2cpp.exe ,而非传递给 mono.exe的参数,首先这里传递了5个标识符给 il2cpp.exe:


–copy-level=None

告诉 il2cpp.exe 不要复制生成的C++代码.

–enable-generic-sharing

IL2CPP将会共享泛型以此来减少最终包体的大小。

–enable-unity-event-support

支持通过反射获取的Unity事件,保证代码能够正确生成。

–output-format=Compact

在生成的C++代码中,为类与方法使用更少的字符数来命名,这样会使得代码更难以调试,因为IL代码的命名将会发生改变(笔者注:应该类似于代码混淆),但是却能够被编译器更快编译,因为编译器所需要解析的字符数变少了。

–extra-types.file=”C:\Program Files\Unity\Editor\Data\il2cpp\il2cpp_default_extra_types.txt”

使用默认的 额外类型文件 ,这个文件会被加入到你的Unity工程里,并告知 il2cpp.exe 哪些泛型类型或者数组类型没有在IL代码中出现,却会在运行时被创建。


值得注意的是这些命令行也许会在后续的Unity版本中发生变化。最后,让我们看看剩下的三条命令行。


  1.  
    “C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\Managed\Assembly-CSharp.dll”
  2.  
    “C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\Managed\UnityEngine.UI.dll”

il2cpp.exe 接受所有应该被转换的 IL 程序集,在这里例子中它应该包含我的 MonoBehaviour脚本、 Assembly-CSharp.dll 以及 GUI assembly 和 UnityEngine.UI.dll ,很显然,上面的命令行里似乎少了些什么, 我的脚本引用了 UnityEngine.dll 和 mscorlib.dll,但是它们却没有被包含在上述的命令行中,那么它们在哪儿呢?事实上,il2cpp.exe 在内部对这些程序集进行了处理,因此在上述的命令行中它们不是必须的,Unity只显式地需要 根程序集(不被任何程序集引用的程序集)在命令行中被提及。

“C:\Users\Josh Peterson\Documents\IL2CPP Blog Example\Temp\StagingArea\Data\il2cppOutput”

最后的一个参数表示 il2cpp.exe 的输出目录,即 il2cpp.exe 生成代码的输出位置,如果你对此感兴趣的话,可以看一看生成目录下的C++文件,而这一块内容我们也会在后续的文章中对其进行详解。此外,如果你希望浏览生成目录下的代码的话,推荐在出包的时候选择 Development Player 模式,这样一来将会移除 –output-format=Compact 命令行,使得你的代码更具可读性。

PS:你可以通过改变 Player Settings 中的设置来观察 Unity 传递给 il2cpp.exe 的命令行的差异,例如将
Enable Exceptions 设置为 Full,那么命令行中就会增加 –emit-null-checks–enable-stacktrace 、 –enable-array-bounds-check 三项.

IL2CPP没有做的工作

Unity官方并没有重写C#的标准库,因此当你发布一个Unity工程的时候,即使你选择了 IL2CPP 的方式来生成你的代码,所有在 mscorlib.dll、System.dll 等标准库中的代码都将使用Mono2X的方式来生成。

作者:StalkerME
链接:https://www.jianshu.com/p/7cfcb7b0cfe7
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

IL2CPP深入详解-总览的更多相关文章

  1. Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览

    一.设计原理 1.Hadoop架构: 流水线(PipeLine) 2.Hadoop架构: HDFS中数据块的状态及其切换过程,GS与BGS 3.Hadoop架构: 关于Recovery (Lease ...

  2. Hadoop3.1.1源码Client详解 : 写入准备-RPC调用与流的建立

    该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览 关于RPC(Remote Procedure Call),如果没有概念,可以参考一下RMI(Remot ...

  3. Hadoop3.1.1源码Client详解 : 入队前数据写入

    该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览 紧接着上一篇: Hadoop3.1.1源码Client详解 : 写入准备-RPC调用与流的建立 先给出 ...

  4. Hadoop3.1.1源码Client详解 : Packet入队后消息系统运作之DataStreamer(Packet发送) : 主干

    该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览 在上一章(Hadoop3.1.1源码Client详解 : 写入准备-RPC调用与流的建立) 我们提到, ...

  5. Hadoop3.1.1源码Client详解 : Packet入队后消息系统运作之ResponseProcessor(ACK接收)

    该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览 紧接着上一篇文章: Hadoop3.1.1源码Client详解 : Packet入队后消息系统运作之D ...

  6. Ubuntu kill命令用法详解

    转自:Ubuntu kill命令用法详解 1. kill   作用:根据进程号杀死进程   用法: kill [信号代码] 进程ID   root@fcola:/# ps -ef | grep sen ...

  7. iOS开发——UI篇OC篇&SpriteKit详解

    SpriteKit详解 SpriteKit,iOS/Mac游戏制作的新纪元 这是我的WWDC2013系列笔记中的一篇,完整的笔记列表请参看这篇总览.本文仅作为个人记录使用,也欢迎在许可协议范围内转载或 ...

  8. Java 8 中的 Streams API 详解

    为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 ...

  9. java日期详解

    [TOC] 一.简介 java中的日期处理一直是个问题,没有很好的方式去处理,所以才有第三方框架的地位比如joda. 文章主要对java日期处理的详解,用1.8可以不用joda. 1. 相关概念 首先 ...

随机推荐

  1. Andorid监听SoftKeyboard弹起事件

    对于Android键盘事件Google并没有提供一个好的接口去监听它,有时候就为项目需要就必须要自己去想办法去监听,由于我最近也要实现登陆与注册的功能,我的想法很简单实现起来也比较容易,主要的原理是在 ...

  2. Windows搭建MongoDB复制集

    ​上篇,我们已经知道了什么是MongoDB的复制集,不知道的可以查看上篇哦,传送门来了. 光说不练,假把式,咱来自己搭建一个复制集.先下载安装哦,不知道的查看上篇哦,https://blog.csdn ...

  3. 你不知道的 IDEA Debug调试小技巧

    一.多线程调试断点 Intellij IDEA 的debug断点调试是有一个模式的选择的,就像下面这张图,平时我们都使用的是默认的 ALL(在Eclipse中默认是线程模式) ,这种模式我们只能将一个 ...

  4. ng service(服务)

    ng service(服务) 创建服务命令:ng g service services/+服务名 使用服务的注意事项: 使用(services)服务需要在app.,module.ts(根模块)中引用并 ...

  5. java架构之路-(面试篇)Mysql面试大全

    说一下mysql比较宏观的面试,具体咋写sql的这里就不过多举例了.后面我还会给出一个关于mysql面试优化的试题,这里主要说的索引和B+Tree结构,很少提到我们的集群配置优化方案. 1.索引是什么 ...

  6. springboot与docker整合

    一.springboot与docker整合 a.创建Dockerfile FROM java MAINTAINER "Wing"<1561815137@qq.com> ...

  7. Java 学习笔记之 Stop停止线程

    Stop停止线程: 使用stop()方法停止线程是非常暴力的,会抛出java.lang.ThreadDeath Error,但是我们无需显示捕捉, 以下捕捉只是为了看得更清晰. public clas ...

  8. IDEA 学习笔记之 安装和基本配置

    安装和基本配置: 下载:https://www.jetbrains.com/idea/download/#section=windows 下载Zip安装包: 基础知识: Eclipse的工作区=IDE ...

  9. MySQL-时区导致的时间前后端不一致

    背景 今天早上刚上班,就被同事提示,程序的日期处理有问题.数据库里日期为:2019-05-21 11:00:00 而前端显示的日期为:2019-05-21 16:00:00 分析 那肯定是和时区相关了 ...

  10. 本次作业统一标题:C语言I博客作业02

    这个作业属于哪个课程 C语言程序设计1 这作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-2/homework/8655 我在这个课程的目标是 ...