福建省建设银行招聘网站,怎么查网站备案域名备案,视频素材网站建设,西安广告公司排名1. 关于lua函数传参参数在lua中给function传递参数的时候一般分为两种情况#xff1a;值传递和引用传递值传递#xff1a;值传递#xff1a;数字、字符串、布尔值、nil等基本类型通过值传递。函数内部接收的是外部变量的副本#xff0c;修改副本不会影响原始变量。
虽然我们…1. 关于lua函数传参参数在lua中给function传递参数的时候一般分为两种情况值传递和引用传递值传递值传递数字、字符串、布尔值、nil等基本类型通过值传递。函数内部接收的是外部变量的副本修改副本不会影响原始变量。
虽然我们都知道字符串是引用类型存储的数据但是在函数传参的时候传递的是指向字符串内存地址的指针值即引用的副本而非原始变量的引用本身function Test(n)n n 1
end
local a 1
Test(a)
print(输出a:..a)
-- 结果a仍然是1引用传递表table和函数如果当作函数的参数传递时传递的时指向具体变量的地址的副本记住时副本可以理解成表本身就是一个指针把这个指针当作参数传递给函数时会重新生成一个指针并且把该变量的指针地址值复制给新生成的指针。所以这种情况下如果直接操作增删都可以正常影响指向的变量数据。但是如果时赋值操作那么就会修改传递过去的副本指向的内容。function Test1(t)t.a 1
endfunction Test2(t)t {a 15,b 3}
endfunction Test3(t)t nil
endlocal t {a 10, b 2}Test1(t)
print(t.a:..t.a.. t.b:..t.b)
Test2(t)
print(t.a:..t.a.. t.b:..t.b)
Test3(t)
print(t.a:..t.a.. t.b:..t.b)上述代码三次的输出都是 t.a:1 t.b:2
.
调用Test1的时候直接修改了引用指向的内容所以修改生效。此时外部的t.a 1。
.
调用Test2的时候直接把引用副本指向了另一个新表的内存那么这时候函数内部的t已经和外部传进去的t没有关系了所以怎么修改都不会对外部的t造成影响。
.
调用Test3的时候和Test2一样把引用副本指向了空同样和外部的t没有关联关系了所以外部t不受影响。2. 关于c#和lua相互引用xlua版
userdata我们都知道lua中有一种数据类型-userdata
.
userdata 是 Lua 为存储 C/C 等外部语言数据而设计的特殊类型提供了一块原始内存区域可直接存放结构体、指针、文件句柄等外部对象。它允许 Lua 通过指针或内存块直接操作外部环境的数据是 Lua 与 C/C 交互的核心机制。例如C 中定义的 struct People 可通过 userdata 传递给 Lua 脚本使用.
.
所以一个语言只要可以和c/c交互那么就可以通过userdata和lua交互这也是c#和lua交互的底层原理。
.xlua中的c#和lua交互在xlua中c#和lua的交互都是通过c这个他们两种语言都能到的媒介实现的。
大致流程如下lua call c#lua调用c# - 调用c - 操作虚拟栈对参数压栈 - 调用c#wrap函数/反射查找函数 -
把lua函数参数转换成c#类型 - 完成调用c# call luac#调用lua - c#调用c函数 - 通过capi找到lua函数(lua_getglobal) - c#数据转成lua数据(lua_pushinteger) -
通过capi调用lua函数(lua_pcall)xlua中c#和lua相互引用
在xlua框架中可以很方便的在lua中持有C#的对象变量并使用反之一样。
lua持有c#对象通过上述的userdata了解我们可以大致了解到其实c#的变量在lua中是以userdata类型的数据存储的。
事实上在lua中从来没有真正的持有c#的真正变量。C#对象在Lua中的表示在xLua中C#对象传递到Lua时会被封装为userdata类型。这个userdata并不直接存储C#对象本身而是存储一个唯一标识符objId用于关联C#端的实际对象引用关系的管理lua持有#但是我们也知道c#的gc是并不清楚lua环境中该userdata的引用情况的如果直接不管lua中是否引用只要c#段就没有引用就GC掉显然不符合我们的需求。所以xlua中设计了ObjectTranslator.cs。
ObjectTranslator通过ObjectPool和ReverseMap维护对象与objId的映射确保C#对象不被GC回收只要Lua仍持有userdata
而在lua中userdata是被存放在弱引用表中的只要lua中没有强引用该对象的存在那么该userdata就可以被lua的gc回收掉防止lua一致持有着objid而c#无法回收对应对象。lua对象在c#中的表示所有Lua对象在C#中通过LuaBase基类管理其构造函数调用luaL_ref在Lua注册表中创建引用析构时调用luaL_unref释放其实讲了那么多就是为了理解如下代码
public class Main{public class TestClass{}public static TestClass MyClassTest;public static TestClass CreateTestClass(){if (MyClassTest null) MyClassTest new TestClass();return MyClassTest;}public static void DestroyTestClass(){MyClassTest null;}
}local myClass,myClass2,myClass3local function Execute()myClass CS.Main.CreateTestClass()myClass2 CS.Main.MyClassTestmyClass3 myClass2myClass2 nilcollectgarbage(collect)CS.System.GC.Collect()CS.Main.DestroyTestClass()collectgarbage(collect)CS.System.GC.Collect()
endpcall(Execute)由上面讲述我们可以知道一个c#变量在lua中的话两端是各自持有各自的类型userdata和TestClass上述lua代码中的myClassmyClass2和myClass3就是对应的userdata。
.
即使myClass2 nil后myClass3和myClass仍然持有该userdata所以第一次执行双方gc只会回收掉myClass2。myClass3和myClass以及c#段的MyClassTest都没收影响。
.
那么再来看CS.Main.DestroyMyClass() 这句之后c#侧的MyClassTest引用被置空注意只是引用实际变量还被lua持有所以即使执行了C#的gc真正的对象仍不会被回收掉因为myClass 和myClass3仍然还存在着并且持有着。
.
那么这时候如何回收掉TestClass对应的数据只需要再加上myClass2 nilmyClass nilcollectgarbage(collect)
CS.System.GC.Collect()
这样的话lua测得强引用也没了都可以被回收了