zoukankan      html  css  js  c++  java
  • IL2CPP深入详解-总览

    导语

    该系列将会分为以下几个部分:
    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 系统中你可以在 EditorDatail2cpp 目录中找到它,
    在 OSX 系统中你可以在 Contents/Frameworks/il2cpp/build,即Unity的安装目录中找到它。
    il2cpp.exe 是由C#编写的受托管的可执行程序,它接受我们在Unity中通过Mono编译器生成的托管程序集,并生成指定平台下的C++代码。

    IL2CPP的工具链如下图所示:

    il2cpp-toolchain

    运行时库

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

    你可以通过查看 libil2cpp 的头文件了解其的代码构成(Windows 系统下的目录为EditorDataPlaybackEngineswebglsupportBuildToolsLibrarieslibil2cppinclude,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 FilesUnityEditorDataMonoBleedingEdgeinmono.exe"
    2.  
      "C:Program FilesUnityEditorDatail2cpp/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 FilesUnityEditorDatail2cppil2cpp_default_extra_types.txt"
    8.  
      "C:UsersJosh PetersonDocumentsIL2CPP Blog ExampleTempStagingAreaDataManagedAssembly-CSharp.dll"
    9.  
      "C:UsersJosh PetersonDocumentsIL2CPP Blog ExampleTempStagingAreaDataManagedUnityEngine.UI.dll"
    10.  
      "C:UsersJosh PetersonDocumentsIL2CPP Blog ExampleTempStagingAreaDatail2cppOutput"

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

    "C:Program FilesUnityEditorDataMonoBleedingEdgeinmono.exe"
    

    首先,Unity启动 mono.exe

    1.  
      "C:Program FilesUnityEditorDatail2cpp/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 FilesUnityEditorDatail2cppil2cpp_default_extra_types.txt”
    

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


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


    1.  
      “C:UsersJosh PetersonDocumentsIL2CPP Blog ExampleTempStagingAreaDataManagedAssembly-CSharp.dll”
    2.  
      “C:UsersJosh PetersonDocumentsIL2CPP Blog ExampleTempStagingAreaDataManagedUnityEngine.UI.dll”

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

    “C:UsersJosh PetersonDocumentsIL2CPP Blog ExampleTempStagingAreaDatail2cppOutput”
    

    最后的一个参数表示 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
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 相关阅读:
    iOS 自动识别URL(链接)功能的实现
    iOS 如何查看崩溃日志
    Swift-- 闭包
    Swift--方法(函数)
    Swift--控制流
    Swift--字典的了解
    数据存储与访问之——SharedPreferences
    汇编指令之STOS、REP
    汇编指令之ADC、SBB、XCHG、MOVS指令
    pushad与popad
  • 原文地址:https://www.cnblogs.com/yptianma/p/11771867.html
Copyright © 2011-2022 走看看