lua_next函数分析

lua_next(L,index):先把 表(lua栈 index所指的表), 的当前索引弹出,再把table 当前索引的值弹出,也就是先弹出 table的索引,再弹出table索引的值

简单一个例子:

<span style="font-family:KaiTi_GB2312;font-size:14px;">NUMBER_TABLE_WITH_INDEX =
{
["a"] = 1,
["b"] = 2,
["c"] = 3
}</span>

<span style="font-family:KaiTi_GB2312;font-size:14px;"> lua_getglobal(L,"STRING_TABLE_WITH_INDEX");
    /*此时lua栈状态
    ----------------------------------
    |  -1 table NUMBER_TABLE
    ----------------------------------
    */</span>

 //循环遍历
    lua_pushnil(L);
    /*此时lua栈状态
    ----------------------------------
    |  -1 nil
    |  -2 table NUMBER_TABLE
    ----------------------------------
    */
    while(lua_next(L,-2))
    {
    /*此时lua栈状态
    ----------------------------------
    |  -1 value
    |  -2 key
    |  -3 table NUMBER_TABLE
    ----------------------------------
    */
        if(lua_isnumber(L,-2))
            cout<<"key:"<<lua_tonumber(L,-2)<<'\t';
        else if(lua_isstring(L,-2))
            cout<<"key:"<<lua_tostring(L,-2)<<'\t';
        if(lua_isnumber(L,-1))
            cout<<"value:"<<lua_tonumber(L,-1)<<endl;
        else if(lua_isstring(L,-1))
            cout<<"value:"<<lua_tostring(L,-1)<<endl;

    /*此时lua栈状态
    ----------------------------------
    |  -1 value
    |  -2 key
    |  -3 table NUMBER_TABLE
    ----------------------------------
    */
        lua_pop(L,1);
    /*此时lua栈状态
    ----------------------------------
    |  -1 key
    |  -2 table NUMBER_TABLE
    ----------------------------------
    */
    }
    lua_pop(L,1);

    /*此时lua栈状态
    ----------------------------------
    |  -1 table NUMBER_TABLE
    ----------------------------------
    */

lua_next函数的工作流程现在大概了解了。还是婆婆妈妈的上一段文字吧:

lua_next() 这个函数的工作过程是:
1) 先从栈顶弹出一个 key
2) 从栈指定位置的 table 里取下一对 key-value,先将 key 入栈再将 value 入栈
3) 如果第 2 步成功则返回非 0 值,否则返回 0,并且不向栈中压入任何值

第 2 步中从 table 里取出所谓“下一对 key-value”是相对于第 1 步中弹出的 key 的。table 里第一对 key-value 的前面没有数据,所以先用 lua_pushnil() 压入一个 nil 充当初始 key。

注意开始的时候先用 lua_gettop() 取了一下 table 在栈中的正索引(前面说过了,在进行这个 lua_next() 过程之前先将 table 入栈,所以栈大小就是 table 的正索引),后面的 lua_next() 过程中不断的有元素出入栈,所以使用正索引来定位 table 比较方便。

到了 table 中已经没有 key-value 对时,lua_next() 先弹出最后一个 key,然后发现已经没有数据了会返回 0,while 循环结束。所以这个 lua_next() 过程结束以后 table 就又位于栈顶了。


详细描述Lua和C之间相互传递Table类型数据 /* ====================================================== */ // 遍历Lua传入的Table类型参数, 获取它的Key/Value, 其关键操作是 lua_next() // lua_next() 返回1表示读取成功,返回0表示已经没有数据可读了 // lua_next() 会使用栈顶元素作为Key去定位本次需要取出Table里面的那个值对 // 如果Key=nil, 那就表示本次取出的是第一个元素 // 它会先将当前的这个Key弹出,然后将本次取出的Key/Value压入栈, Value在栈顶 // 一个比较隐晦的处理就是, 我们不应直接使用lua_tostring(L, -2)来读取Key // 因为lua_tostring()在Key类型不是字符串时, 它会修改栈上的Key数据 // 这样, 下次调用lua_next()时, 就会因为Key被修改了而导致错误 // 为此,先调用lua_pushvalue(L, -2),将它Copy一份到栈顶,对这个Copy进行lua_tostring() // 读取Key,Value到C变量里面后,将Value和Copy弹出,留着Key在栈顶,给下次lua_next()用 // // 指令及栈图变化如下: (假如Table的栈下标是Index) // 0. 刚进入函数时 ...Table, ... <--- 这里栈顶 // 1. lua_pushnil(L) ...Table, ..., nil <--- 这里栈顶 // 2. lua_next(L, Index) ...Table, ..., Key, Value <--- 这里栈顶 // 3. lua_pushvalue(L, -2) ...Table, ..., Key, Value, KeyCopy <--- 这里栈顶 // 4. lua_pop(L, 2), ...Table, ..., Key <--- 这里栈顶 // ... 如此重复2,3,4 // N. lua_next(L, Index)返回0 ...Table, ... <--- 这里栈顶 /* ====================================================== */
`lua_rawlen` 是 Lua C API 中的一个函数,用于获取一个 Lua 对象(如字符串、表、userdata 等)的原始长度。它是在 **Lua 5.2** 及以上版本中引入的函数,用来替代旧版本中的 `lua_objlen`。 --- ## ✅ 函数原型 ```c size_t lua_rawlen (lua_State *L, int index); ``` - `L`: Lua 虚拟机的状态指针。 - `index`: 栈上的索引值(可以是正数或负数)。 ### 返回值: - 返回对象的“原始”长度: - 如果是字符串:返回字节数; - 如果是表:返回数组部分的最大整数键 + 1(不调用元方法); - 如果是 userdata:返回分配的内存块大小; - 其他类型返回 0。 --- ## ✅ 示例代码 下面是一个使用 `lua_rawlen` 获取 Lua 表长度的例子: ```c #include <lua.h> #include <lauxlib.h> #include <lualib.h> #include <stdio.h> int main() { lua_State *L = luaL_newstate(); // 创建新的 Lua 状态 luaL_openlibs(L); // 打开标准库 // 创建一个 Lua 表并压入栈顶 lua_newtable(L); // 填充表 { [1] = 10, [2] = 20, [3] = 30 } for (int i = 1; i <= 3; ++i) { lua_pushinteger(L, i * 10); // value = i * 10 lua_rawseti(L, -2, i); // table[i] = value } // 使用 lua_rawlen 获取数组部分的长度 size_t len = lua_rawlen(L, -1); printf("Length of array part: %zu\n", len); // 输出:3 lua_pop(L, 1); // 弹出表 lua_close(L); // 关闭 Lua 状态 return 0; } ``` --- ## ✅ 与 `#` 操作符和 `lua_objlen` 的区别 | 方法 | 是否调用元方法 | 支持类型 | 备注 | |------|----------------|----------|------| | `#LUA_TABLE` | ✅ 是 | 表 | 会调用 `__len` 元方法 | | `lua_objlen(L, idx)` | ❌ 否 | 表、字符串等 | Lua 5.1 及以前使用 | | `lua_rawlen(L, idx)` | ❌ 否 | 表、字符串、userdata 等 | Lua 5.2+ 推荐使用 | --- ## ✅ 注意事项 - `lua_rawlen` 不会触发任何元方法(比如 `__len`),因此它是“raw”的。 - 对于表来说,它只返回数组部分的长度(即连续的从 1 开始的整数键数量),而不是整个表的元素个数。 - 如果你想获得表中所有键的数量,你需要手动遍历表。 --- ## ✅ 遍历表获取实际元素个数的示例 ```c int count_table_elements(lua_State *L) { int count = 0; lua_pushnil(L); // 初始 key while (lua_next(L, -2) != 0) { count++; lua_pop(L, 1); // 弹出 value,保留 key 用于下一次迭代 } return count; } ``` --- ## ✅ 总结 | 功能 | 函数 | |------|------| | 获取字符串长度 | `lua_rawlen(L, idx)` | | 获取表的数组部分长度 | `lua_rawlen(L, idx)` | | 获取表的实际键值对数量 | 手动遍历表 | | 获取 userdata 分配的大小 | `lua_rawlen(L, idx)` | --- ###
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值