通常Lua堆栈从索引1开始。但是,当读取通过调用cfunction提供的堆栈地址0时,我注意到一个奇怪的现象。
--lua tables defined via Lua C API
h{ }
u{ }
f{ u{ s{} } }
--table calls
h(2)
u(3)
f.u.s(4)
上述所有表格(h
,u
和嵌套s
)都有__call
元方法指向同一个cfunction。从那个函数我正在读取/转储传递的堆栈:
while(start_index <= lua_gettop(state)) {
switch(lua_type(state, start_index)) {
case LUA_TNUMBER:
std::cout << "LUA_TNUMBER:"<<lua_tonumber(state, start_index);
break;
//... dump for all the other types
当start_index
从1开始时,输出符合预期:LUA_TABLE LUA_TNUMBER:3
;它包含的表包含metamethod(或者我认为)和参数3
。
但是当start_index
从0开始时,我认为结果不是有效的Lua类型,但确实如此。结果不一致:从Lua调用时,索引0
始终为LUA_TNUMBER
,其值为5
。
然而,当使用pcall(lua_getfield, lua_pushnumber, lua_pcall
)从C ++调用时,索引0为调用LUA_TNUMBER(5)
产生相同的f.u.s
,而LUA_TABLE
和h
产生u
{1}}。
什么是索引0,为什么它是一个有效的Lua类型,为什么它的值如此奇怪地不一致?
答案 0 :(得分:4)
0不是有效的堆栈索引,因此您无法依赖于在那里找到任何内容。它有点像拿lua_State
指针和解除引用(lua_State - 1)
并询问它的值是什么。这是垃圾。
来自Lua manual:
接收堆栈索引的API中的任何函数仅适用于有效索引或可接受索引。
有效索引是一个引用堆栈中实际位置的索引,也就是说,它的位置介于1和堆栈顶部之间(1 = abs(index)= top)。
可接受的索引可以是任何有效索引,包括伪索引,但它也可以是在为该分配的空间内的堆栈顶部之后的任何正索引堆栈,即索引到堆栈大小。
(注意0绝不是可接受的索引)
查看源代码(请参阅index2addr),看起来如果Lua是使用LUA_USE_APICHECK
生成的,那么您的调用将会抛出错误。