xLua 是目前 Unity 热更新中用的比较多的方案之一,花了些时间看了下代码,并对其中的 Lua 和 C#中对象的传递与内存管理有了一些个人理解,可能理解有误,欢迎批评指正
C#对象传递到 Lua
Unity 中 C#对象可以大致分成几类:继承自 primitive 类型、string 类型、struct 类型、enum 类型和类对象,这几种类型的对象有不同的处理逻辑,分为如何将对象传递到 lua 中,当从 lua 中传递回 C#时如何找到对应的 C#对象,以及何时释放对象的引用避免内存泄漏几个方面
-
primitive 类型
primitive 类型不参与 GC,所以直接调用lua_pushxxx
函数,Lua 传递到 C#时也是直接调用lua_toxxx
即可 -
string 类型
string 类型和 primitive 一样,直接调用lua_pushstring
函数,Lua 传递到 C#时直接调用lua_tostring
即可 -
类对象
类对象会参与 GC,会把 Lua 查找 C#对象的映射关系存储到 objects 对象中,映射关系存储到 reverseMap 中,这样后续可以直接复用之前的对象因为回存在对象回收的问题,所以会对在 Lua 中创建的相应关系的 LuaTable 注册名为
__gc
的 metatable,这样在 Lua 对象被 GC 的时候,可以完全清除掉 objects 对象中对 C#对象的引用,避免内存泄漏,同时 objects 对象中也是一个会扩容的对象池,清除掉引用之后就也可以复用直接的 id,避免无限扩容对于继承自
UnityEngine.Object
的对象因为重写了==
运算符还会有特殊逻辑,需要使用者在合适的时机(一般来讲是Update
方法中间隔固定时间)调用LuaEnv
上的Tick
方法,这样可以在UnityEngine.Object
对象被销毁后及时将 objects 中 Lua 查找 C#的映射关系单向清理掉,避免内存泄漏,反向的映射关系还是需要等到上面提到的__gc
方法中清除,避免使用者将 lua 对象再次传回 C#中后因为复用查找到不同的对象出现错误 -
enum 类型
枚举类型是固定不变的,不需要参与 GC,会把通过 Lua 查找 C#的映射关系存储到 objects 对象中,C#到 Lua 的映射关系存储到 enumMap 对象中,这样在后续的使用中都会直接复用之前的对象 -
struct 类型
因为 c#中 struct 为值类型,所以会出现当一个 struct 对象传递到 Lua 后再传递回 C#就不会是同一个对象了,如果只是使用例如 Color 或者 Vector 等 struct 是没有问题的,但是对于一些内部带有状态的 struct 是会出现问题的,这点需要额外注意
Lua 对象传递到 C#
Lua 中常用的会传递到 C#中的类型有几种:boolean、number、string、table、function,其中 boolean、number、string 都是用是直接值传递方式
- function
function 一般来讲是对应 C#中的 delegate,但是因为 lua 为弱类型,C#为强类型,所以需要一个比较复杂的包装处理,首先会包装成DelegateBridge
对象,然后使用getDelegate
函数根据需要的 delegate 类型做一层转换包装处理,返回DelegateBridge
对象上一个具体的需要的类型的成员函数,并将 lua 对象在 C#中的映射关系存储到 delegate_bridges 中,这样在下次将这个函数从 lua 中传递到 C#中时可以直接复用已有对象
此外,还有个类叫做LuaFunction
也可以实现用于将 lua 对象传递到 C#中使用的功能 - table
table 的情况比较复杂,常见的分成几种情况:- table 转换为 C#中 struct,这种情况就是直接构造了一个 struct 对象然后队成员变量赋值
- table 转换为 interface,这种情况需要 xLua 生成一个继承自对应 interface 的一个实现类,并对里面所有的抽象方法利用 Lua 的 C API 生成对应的具体实现
- 直接将 table 封装为
LuaTable
对象,等到具体使用的时候直接调用LuaTable
对应方法获取上面的函数或变量
DelegateBridge
、实现 interface、LuaTable
等方式都需要注意,他们都会对对应的 table 产生一次引用,而且他们(包括其他类似类也是一样)都继承自 LuaBase
,会在析构函数中解除对 table 的引用,避免内存泄漏
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于