第四个案例讲的如何获取lua中的变量的几种情况。
1、我们可以使用“[]”操作来获取lua中的变量。在LuaState中定义了"[]"操作符。注意,lua片段必须被载入才能被读取到,具体到本例,就是调用DoString()方法,否则读取到变量为空。本例中一开始设置了一个变量的值,这里涉及了"[]"操作符的set操作。set操作中,对于要获取的lua变量分了两种操作,一种就是全局的变量(存在于_G中),一种就是某个table的变量。这两种类型,核心操作都是两步,将要设置的值压栈,再设置对应lua变量的值。
压栈的时候,会判断value的类型,调用对应的方法进行压栈。核心方法是ToLua.Push()。这里面有一点需要注意的就是,方法会先判断该类型是不是空类型(?),如果是空类型,会有一步赋值的操作。
这里,整型被归为了一种Primituve属性,在这里会将其转变成Double类型,返回。
LuaSetGlobal()就是设置值的核心方法,本例中变量是全局变量对应使用该方法。
对于lua变量的get方法,非全局变量,获取到table名字后,会将其做压栈处理(不在栈内就压栈,否则就直接返回)。同时变量名也要做压栈处理。最后通过ToVariant()获取其值。
2、通过“[]”获取lua中的方法。前面的例子中使用的是GetFunction()方法获取到了lua中的方法。通过单步跟踪可以方法,该方法本质上还是使用的GetFunction()方法来获取lua中的function。但是这里对于方法的调用,却使用的Call()方法,可以看到,对比Invke()方法,该方法是没有返回值的,其他则和Invoke()没有区别。
3、对lua中table的操作。可以看到:
3.1、使用GetTabel()获取lua中的table。
3.2、使用“[]”对table中的元素进行操作,索引的对象是获取到的table对象。
3.3、使用AddTable(),创建一个table。
3.4、使用GetMetTable()获取一个table的原表。
3.5、使用ToArray()将一个数组类型的table转变成C#数组
通过单步跟踪,发现GetTable()方法也是有一步从funcMap中获取值的步骤。可以想象,该字典应该是用于存储lua中的引用,例如function,table之类的类型。如果在funcMap中查不到对应的table,则会将需要查找的table进行压栈处理,同时会在funcRefMap字典中查找对应的引用,如果还是找不到就直接创建一个LuaTable实例。在创建LuaTable实例的时候,会先初始化基类luaBaseRef的几个字段:
创建完成后,将名字进行赋值,然后添加到funcMap,funcRefMap字典中去。
table的读取使用的是LuaTable的"[]"操作符。可以看到set和get方法的不同之处:
Push(this)方法是在获取luastate引用,而Push(key)则是将table的索引压栈。get和set不同之处在于,get方法会从栈里面获取table引用,转换成lua中的table类型返回。而set方法则多一步将新值压栈,设置新值的过程。这里的将新值压栈和设置lua中变量的核心方法是一样,都是ToLua.Push()。
创建table的方法,可以看到,AddTable()方法,和上面的“[]”操作符一样,都走了两步Push()方法。LuaCreateTable()方法是核心方法。最后再设置索引。
值得注意的是,该空table的获取用的是之前的LuaTable对象的“[]”操作符获取的。因为创建该空table就是使用的之前table的LuatTable的实例的成员方法创建的,所以才可以索引到。将其强转为LuaTable对象后,就可以进行操作了。