作者:王攀峰, 腾讯游戏客户端开发 工程师
商业转载请联系腾讯 WeTest 获得授权,非商业转载请注明出处。
原文链接:http://wetest.qq.com/lab/view/387.html

WeTest 导读

CsToLua 工具将客户端 C# 源码自动转换为 Lua,实现热更新,本文以麻将项目为例介绍客户端技术细节。


麻将项目架构

其中 ChinaMahjong-CSLua 为 C# 工程,实现麻将项目的主要业务流程。翻译工程的输入是 C# 项目生成的 dll 文件。其中 Cecil 负责分析类型 类成员关系 ,比如类字段函数结构,引用关系、类之间的继承关系等,ILSpy 负责反编译函数体里的语句,比如条件语句,函数调用,算数运算等。下面逐个介绍具体的实现。

Mono.Cecil

Mono.Cecil:一个可加载并浏览现有程序集并进行动态修改并保存的.NET 框架。可以静态注入程序集(注入后生成新的程序集)和动态注入程序集(注入后不改变目标程序集,只在运行时改变程序集行为。麻将项目入口:

举一个 Mono.Cecil 例子,这是原始的 Unity C# 代码:

我们采用 Cecil 工具对生成的 Dll 进行代码嵌入,具体的嵌入逻辑如下:


OpCodes.Ldstr 字段:推送对元数据中存储的字符串的新对象引用。指令将一个对象引用推送 (类型 O) 到一个新的字符串对象,表示存储的元数据中的特定字符串文字;

OpCodes.Call 字段:调用由传递的方法说明符指示的方法。

反编译嵌入自定义逻辑代码,实现了原生代码功能的更新。也就是说在没有源代码的前提下,Mono.Ceil 可以动态嵌入指定代码至可执行文件。(这也是一些外挂的套路,也有加壳和加密技术来提升反编译的难度了,此处省去一万字)上面的代码等价于如下:

Mono.Cecil 底层是如何处理的呢,再举一个例子,这是原始的 C# 代码:

上面是 C# 逻辑打包成 dll 后,采用 Cecil 反编译得到的内容如下,具体逻辑见注释:

用 Mono.Cecil 得到了二进制文件的中间代码,中间代码是一种基于操作栈的虚拟机语言,指令间借助栈传递数据。

ILSpy

ILSpy 是一个开源.Net 的反编译器,能把 C# 生成二进制文件转换为 MSIL 或者 C# 任选一种。因为项目 C# 程序集是团队开发,因此不需要破解加密算法和去壳等操作。相关的反编译软件有:ilasm、.Net Reflector 和 Just Decompile 等。

ILspy 的主要功能:从 Mono.Cecil 拿到具体类型,类型定义的方法,以及各自的 MethodBody。然后对 MethodBody 中的 IL Instructions(指令代码)做数据流分析和控制流分析。如下为 ILSpy 的输人内容:

举个例子,说明一下 ILSpy 具体的实现流程,如下为 C# 源码:

通过 Mono.Ceil 和 ILSpy 分析后的输出:

ILSpy 对 IL Instructions 以跳转指令为界限,划分了基本的 block,block 间构成树形结构:

TK_CSLua

TK_CSLua 根据不同的语句块实现具体的翻译逻辑,比如将 C# 中的 while 循环,生成 Lua 里面的 while-end 逻辑等。翻译过程是一个递归的过程,如图为不同类型的语句块处理逻辑:

while 循环的处理逻辑为:

最终自动生成了 Lua 代码,如下所示:

ToLua

ToLua 基于 LuaInterface,LuaInterface 是一个实现 Lua 和微软.Net 平台的 CLR 混合编程的开源库,使得 Lua 脚本可以实例化 CLR 对象,访问属性,调用方法甚至使用 Lua 函数来处理事件。提供了一套中间层导出工具,对于需要访问的 CLR、Unity 及自定义类预生成 Wrap 文件,Lua 访问时只访问 Wrap 文件,Wrap 文件接收 Lua 传递来的参数,进行类型(值、对象、委托)转换,再调用真正工作的 CLR 对象和函数,最后将返回值返回给 Lua ,有效地提高了效率。

Lua 虚拟机启动主流程:

Unity C# 与 Lua 交互,麻将项目主要采用了 Wrap 文件这种非反射的方式实现。以下为生成绑定的具体流程:

生成后的 WrapperConfig 文件如下所示:

举个例子说明绑定的具体实现,C# 代码如下:

ToLua 绑定后生成的代码:

C# 中的对象在传给 Lua 时并不是直接把对象暴露给了 Lua,而是在这个 OjbectTranslator 里面注册并返回一个索引,并把这个索引包装成一个 userdata 传递给 Lua,并且设置元表:

数据包装如下:

游戏启动

麻将项目启动入口为 Init.Lua:

加载配置,进入登录场景。


UPA—— 一款针对 Unity 游戏/产品的深度性能分析工具,由腾讯 WeTest 和 unity 官方共同研发打造,可以帮助游戏开发者快速定位性能问题。旨在为游戏开发者提供更完善的手游性能解决方案,同时与开发环节形成闭环,保障游戏品质。

点击链接:http://wetest.qq.com/cube/ ,下载 WeTest 助手 APP ,立即使用 UPA,


腾讯 WeTest 有奖征文活动进行中,欢迎投稿!了解详情:
http://wetest.qq.com/lab/view/379.html


↙↙↙阅读原文可查看相关链接,并与作者交流