本文借鉴《自己动手实现Lua:虚拟机、编译器和标准库》,算是对自己学习的总结,也希望分享下所学知识~~
lua的二进制chunk和java的class文件类似
本质上也是一个字节流
注意:
1.二进制chunk没有考虑跨平台的需求,对于需要使用超过一个字节表示的数据,表需要考虑大小端(Endianness)的问题
2.二进制chunk格式的设计也没有考虑过不同Lua版本之间的兼容问题。当编译Lua脚本时,直接按照当时的Lua版本生成二进制chunk文件,当加载二进制chunk文件时,会检查被夹在文件的版本号,如果和当前Lua版本不匹配,则拒绝加载
3.二进制chunk文件并不紧凑,一些情况下Lua被编译成二进制chunk之后,甚至会比文本格式的原文件还要大。因为其主要的目的是获得的更快的加载速度
数据格式:
二进制chunk内部使用的数据类型大致可分为数字、字符串和列表三种
(因为Lua是用C语言写的,所以C语言的一些数据类型会直接反映在二进制chunk的格式里)
1.数字
主要有五种:
a.字节**(占用字节:1)**
主要是存放一些比较小的整数值,比如Lua版本号、函数的参数个数等
b.C语言整形(cint)(占用字节:4)
主要用来表示列表长度
c.C语言size_t类型(size_t: [typedef unsigned long size_t])(占用字节:8)
主要用来表示长字符串长度
d.Lua整型**(占用字节:8)**
e.Lua浮点数**(占用字节:8)**
这俩主要在常量表出现,记录Lua脚本中出现整数和浮点数字面亮
数字类型在二进制chunk里都按照固定长度存储
2.字符串
字符串在二进制chunk里,其实就是一个字节数组
字符串长度是不固定的,所以需要把字节数组的长度也记录到二进制chunk里
字符串类型可以根据短字符串和长字符串进行进一步优化
a.对于NULL字符串,只用0x00表示就可以了
b.对于长度小于等于253(0xFD)的字符串,先使用一个字节记录长度+1,然后是字节数组(2^8=256,4位存长度,剩下253位可以存字符串)
c.对于长度大雨等于254(0xFE),后面跟一个size_t记录长度+1,最后是字节数组
3.列表
在二进制chunk内部,指令表、常量表、子函数原型表等信息都是按照列表的方式存储的
列表其实就是:先用一个cint类型记录列表长度,然后紧接着存储n个列表元素