Lua数据类型(源码解析)
我们都知道Lua是一门动态类型的脚本语言,也就是说同一个变量可以在不同的时刻指向不同类型的数据。例如
而在Lua中有8中基础的数据类型:nil(空),boolean(布尔),number(数字),string(字符串),table(表),function(函数),userdata(自定义类型),thread(协程),那这几种基础类型在Lua中是怎么定义的,而Lua又是怎么实现动态类型的呢?
Lua是使用C语言实现的一种脚本语言,那么我们如果我们想在C语言中实现一种新的通用的数据类型一般会怎么去做呢?
定义一个结构体,这个结构体中一定要有 一个字段来存储当前结构体所表示的数据类型 ,同时需要一些字段来 存储不同数据类型的具体数据
先看一下Lua中定义的几种基本数据类型的宏:
这些宏对应的数据类型如下表:
lua_Number对应的C语言的基本数据类型double,所以Lua中的number类型表示的都是实数(双精度浮点数),Lua中没有整数类型。
LUA_TLIGHTUSERDATA和LUA_TUSERDATA都是void *(指针类型)。根据名字我们知道他们对应的是Lua的userdata基本数据类型,但是两者是有一些区别的。LUA_TLIGHTUSERDATA表示那些内存分配与释放都是由Lua外部的使用者要管理的对象,而LUA_TUSERDATA表示的都是通过Lua来管理生命周期的对象,也就是LUA_TUSERDATA指向的对象是需要加入到Lua的GC(Garbage Collection 垃圾回收)中的。
我们知道Lua有自己的GC机制,那么哪些基础数据类型需要加到GC中,哪些又不需要,怎么区分呢?
在Lua中用一个宏来表示哪些数据类型需要进行GC操作:
所以说LUA_TSTRING之前的数据类型是都不需要GC,也就是string,table,function,userdata,thread都需要GC的。
在Lua中需要进行GC操作的数据类型都会有个CommonHeader宏定义的成员,并且这个成员在定义的最开始部分。
next : 指向下一个GC链表的成员
tt : 表示数据的类型,即前面的那些表示数据类型的宏
marked :GC时,相关的标记位。
到了这里我们可以使用一个 共同体(union) ,将所有需要进行GC的数据类型囊括起来:
所以GCObject可以表示Lua中所有需要GC的数据类型。
既然所有需要GC的数据类型使用GCObject表示,那么同理所有的数据类型也可以用一个共同体表示:
结合我们(一)中所说的,我们现在有了可以表示所有类型数据的Value了,那么就还需要一个表示数据类型的字段,所以Lua中给我们定义了一个TValue的结构体:
从这个结构体我们可以看到使用int类型的tt字段表示当前的数据类型,使用Value来表示任意类型的值。这样TValue就可以表示Lua中任意的数据类型了。
我们用一个图来表示一下Lua通用的数据结构的组织:
o为通用数据类型TValue,tt则为TValue结构体中表示具体数据类型的字段。
2023-08-15 广告