lua源码剖析.doc
上传人:sy****28 上传时间:2024-09-15 格式:DOC 页数:35 大小:1.1MB 金币:16 举报 版权申诉
预览加载中,请您耐心等待几秒...

lua源码剖析.doc

lua源码剖析.doc

预览

免费试读已结束,剩余 25 页请下载文档后查看

16 金币

下载此文档

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

lua源码剖析先来看lua中值的表示方式。Java代码#defineTValuefieldsValuevalue;inttttypedefstructlua_TValue{TValuefields;}TValue;其中tt表示类型,value也就是lua中对象的表示。Java代码typedefunion{GCObject*gc;void*p;lua_Numbern;intb;}Value;gc用于表示需要垃圾回收的一些值,比如string,table等等。p用于表示lightuserdata它是不会被gc的。n表示doubleb表示booleantvalue这样表示会有空间的浪费.可是由于要完全符合c99,因此只能这么做.否则我们为了效率可以这么做.由于在大多数机器上,指针都是严格对齐(4或者8字节对齐).因此后面的2,3位就是0,因此我们可以将类型存储在这几位,从而极大地压缩了Value的大小.更新:这里经的HYPERLINK"http://www.zhuzhaoyuan.com/"\t"_blank"老朱同学的提醒,其实tvalue之所以不使用指针的后几位来存储类型,更重要的时候由于和c的交互.因为那样的话,我们就必须强制和lua交互的c模块也必须保持和我们一样的内存模型了.lua_state表示一个lua虚拟机,它是per-thread的,也就是一个协程(多个和lua交互的c程序,那自然也会有多个lua-state)一个lua_state,然后来看它的几个比较重要的域。StkIdtop这个域表示在这个栈上的第一个空闲的slot。StkIdbase这个域表示当前所在函数的base。这个base可以说就是栈底。只不过是当前函数的。StkIdstack_last在栈上的最后一个空闲的slotStkIdstack栈的base,这个是整个栈的栈底。StkId是一个Tvalue类型的指针。在lstrlib中,基本上所有的str函数都是首先调用luaL_checklstring来得到所需要处理的字符串然后再进行处理。如果是需要改变字符串的话,那么都会首先生成一个luaL_Buffer对象(主要原因是在lua中,都会做一个传递进来的字符串的副本的),然后最终将处理的结果通过调用luaL_pushXXX放到栈中。luaL_checklstring函数,这个函数只是简单的对lua_tolstring进行了一层简单的封装。而luaL_tolstring也是对index2adr函数做了一层简单封装,然后判断所得到的值是否为字符串,是的话返回字符串,并修改len为字符串长度。Java代码LUALIB_APIconstchar*luaL_checklstring(lua_State*L,intnarg,size_t*len){///通过luaL_tolstring得到字符串sconstchar*s=lua_tolstring(L,narg,len);if(!s)tag_error(L,narg,LUA_TSTRING);returns;}因此我们详细来看index2adr这个函数,这个函数目的很简单,就是通过索引得到对应的值的指针。第一个参数lua_state,第二个参数为索引值。我们首先要知道在lua中,索引值可以为负数也可以为正数,当为负数的话,top为-1,当为正数第一个压入栈的元素为1,依此类推.而且有些类型的对象当转换时还需要一些特殊处理,比如闭包中的变量。除去特殊的,一般的存取很简单,当index>0则我们只需要用base+i-1来取得这个指针,为什么要用base而不是top呢,我们上面已经说过了,当index为正数,所取得的是第一个值,因此也就是栈的最下面那个值,而base表示当前函数在栈里面的位置,因此我们加上i-1就可以了。当index<0则更简单,我们用top+index就可以了。Java代码staticTValue*index2adr(lua_State*L,intidx){if(idx>0){///索引为正值时,通过base取得valueTValue*o=L->base+(idx-1);api_check(L,idx<=L->ci->top-L->base);///如果超过top,则返回nil,否则返回o。if(o>=L->top)returncast(TValue*,luaO_nilobject);elsereturno;}elseif(idx>LUA_REGISTRYINDEX){///正常的小于0的索引。则直接通过top+idx取得对象。api_check(L,idx!=0&&-idx<=L->top-L->base);returnL->