1.Unlua源码解析(附) 读源码的前置知识
2.tolua源码分析(五)lua使用C#的enum
Unlua源码解析(附) 读源码的前置知识
在解析Unlua源码时,需要熟悉Lua的基本API和交互机制。以下为关键API及功能解析:
1. lua_getfield(L, k):获取指定表中由key k指向的值,压入栈顶。
2. lua_gettop(L):返回栈顶元素的索引,即栈的巅峰数卡源码大小。
3. lua_rawget(L, -2):与lua_getfield类似,获取t[k]的值压入栈顶,但不调用元方法。
4. lua_rawset(L, -4):设置t[k] = v,同样不通过元方法。
5. lua_remove(L, -2):移除栈中index为-2的内容,之后所有元素下移。
6. Lua与C++交互机制:调用开始时,屠龙传说 源码Lua参数依次压入栈;调用结束时,C++返回值压入栈,同时返回值数量。
在lua.h中,lua与C交互的API如下:
1.1 lua_register:将C函数设置为全局名称的新值,允许Lua端调用。
1.2 lua_gettop:返回栈顶元素的索引,用于获取栈大小。
1.3 lua_pop:弹出栈中指定数量的值。
1.4 lua_tolstring:将指定位置的值转换为C字符串,并返回字符串长度。
1.5 lua_tostring:与lua_tolstring类似,但返回长度为NULL。兑换商城 源码
1.6 lua_getfield:将表中key指向的值压入栈顶。
1.7 luaL_getmetatable:获取指定表的元表并入栈。
1.8 luaL_newmetatable:创建新元表并入栈,或重用已有。
1.9 lua_getmetatable:获取指定索引处的表的元表。
1. lua_pushstring:将字符串入栈,Lua会做拷贝。
1. lua_settable:设置表中key对应的值。
1. lua_rawset:与lua_settable类似,不调用元方法。
1. lua_gettable:从表中获取key对应的值。
1. lua_rawget:与lua_gettable类似,不调用元方法。私募 源码
1. lua_pushinteger:将数字入栈。
1. lua_pushlightuserdata:将指针入栈。
1. lua_pushcclosure:创建闭包入栈。
1. lua_pushvalue:复制指定位置的值入栈。
1. lua_setmetatable:设置表元表。
1. lua_getglobal:获取全局变量并入栈。
1. lua_setglobal:设置全局变量值。
1. lua_pushnil:入栈nil值。
1. lua_upvalueindex:获取闭包中的upvalue。
1. lua_touserdata:返回完整 userdata 或 light userdata 指针。
1. lua_newtable:创建空表并入栈。
1. lua_createtable:预分配空间后创建空表。
1. lua_next:用于遍历表元素。LiSiR ios源码
1. lua_tolstring:将指定位置的值转换为C字符串。
1. lua_tostring:与lua_tolstring类似,但不返回长度。
1. lua_newuserdata:分配内存并创建 userdata。
1. lua_call:调用Lua函数。
1. lua_pcall:与lua_call类似,用于调用Lua函数。
在Lua中,存在一些全局方法如rawset和rawget,用于直接写入或读取表元素而避免元方法的调用。
综上所述,通过掌握这些API,开发者能有效利用Lua与C++的交互机制,实现复杂、高效的数据处理和逻辑交互。
tolua源码分析(五)lua使用C#的enum
探讨了C#枚举如何在Lua中注册以及与普通类的注册区别。以官方提供的例子为例,展示了如何将C#的UnityEngine.Space类型的枚举推送到Lua层,并在Lua层面测试了诸如tostring、ToInt、Equals等接口,验证了在Lua层可以进行枚举的相等判断,以及将int转换为枚举或将枚举转换为int的操作。
在Lua层面表示C#的枚举,例子中在第行和第行将枚举推送到Lua层。由于枚举是值类型,C#层使用了enumMap缓存装箱后的object与枚举的映射关系。注册到Lua层的枚举类使用了EnumMetatable。
具体来看C#枚举注册到Lua的方法,例如在System_EnumWrap.Register方法中。在Lua层表示C#枚举的方式与普通类相似,但需要注意一些区别。
例如,当使用__tostring方法时,ToLua.ToObject将Lua栈上的userdata转换为object,通过userdata的index查找C#的object缓存,不会产生垃圾收集(GC)。同样地,ToInt方法中的CheckObject同样在C#的object缓存中查找,执行类型检查,也不会产生GC。
当比较C#的枚举与int类型时,由于使用了==操作符,这会触发装箱,产生一次GC。因此,在实际使用中应尽量避免在Lua层对C#枚举与number进行比较。而在Lua层直接比较两个C#枚举时,它们在Lua层被视为同一份userdata,因为它们来自于同一个C#缓存,index相同。
在将Lua栈上的number转换为C#枚举的实例时,IntToEnum方法在C#的UnityEngine_SpaceWrap类中实现。这个方法直接将double转换为int,再转换为UnityEngine.Space类型,避免了GC。在C#层推送到Lua层的枚举时,是从C#的缓存中取到枚举对应的object,然后推送到Lua层,也不会产生GC。
总结,在Lua使用C#的枚举时,从C#到Lua层的传递不会产生GC,在Lua层进行number与枚举类型之间的转换以及直接比较枚举时不触发GC。然而,当比较枚举与number时,会触发一次GC。针对这一情况,可以进行针对性优化。
下一节将深入研究在开发中常见的C#委托/事件如何注册到Lua函数的实现。