lua_gettable 函数详解

        在开发 C/C++ 与 Lua 交互程序的过程中,Lua_gettable() 经常会使用,函数声明在 lua.h 里,其实现是在 liblua.a 库里。该函数原型为:

int lua_gettable (lua_State *L, int index);

Pushes onto the stack the value t[k], where t is the value at the given index and k is the value at the top of the stack.

This function pops the key from the stack, pushing the resulting value in its place. As in Lua, this function may trigger a metamethod for the "index" event (see §2.4).

Returns the type of the pushed value.

参数:

L: 一般是通过 luaL_newstate() 获取

index: 这个并不好理解,这个index所指向的值,就是你想要获取的对象。

翻译成中文就是:把t[k] 的值压入栈,这里的t指有效索引index指向的值,而k则是栈顶放的值。这个函数会弹出栈上的key,把结果放在栈上相同的位置,即把table[key]对应的值放到栈顶。

光靠文字其实是不好理解的,需要结合代码来理解,但在此之前开发人员必须时刻在脑子里有一个栈的数据结构,以及每个对象在栈中的位置。如果栈中对象的位置搞错,则很多带有 index 参数的函数可能都取不到正确的结果。

有 init.lua 脚本如下:


--定义了一个全局表
COM = {}

--定义了一个局部函数
local function add(a, b)
    print("a = "..a);
    print("b = "..b);
    return a + b;
end

COM = 
{
    width = 2550,
    myAdd = add,
}

ATMCtrl = {
    channalNum = 8,
    title = "ATM machine"
}


Global = {
    AtmCtrl = ATMCtrl
}

定义了一个 table 名为 Global,为全局变量。此 table 内容里有一个对象名为 AtmCtrl,此对象也是一个 table,此 table 里有两个元素。下面我要取到 ATMCtrl 里的元素 title 的值,该怎么获取呢?看如下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>    
}
#endif

int main()
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    if(luaL_loadfile(L, "init.lua"))
    {
        printf("load file: hello.lua faild...\n");
        lua_close(L);
        return 1;
    }
    lua_pcall(L, 0, 0, 0); /* 前面这几步都基本固定 */
    
    lua_getglobal(L, "Global");         /* 先找到表 */
    if(lua_type(L, -1) != LUA_TTABLE)    
    {
        printf("can not find table: Global \n");
        lua_close(L);
        return 1;
    }

    lua_pushstring(L, "AtmCtrl");    /* 将要找的关键字入栈 */
    int type = lua_gettable(L, -2);  /* 如果找到则将 AtmCtrl 的值入栈,即放到栈顶 */

    if(lua_type(L, -1) != LUA_TTABLE)    /* 栈顶是否是要找到类型 */
    {
        printf("AtmCtrl is not a table\n");
        lua_close(L);
        return 1;
    }

    lua_pushstring(L, "title");
    type = lua_gettable(L, -2);
    printf("get type: %d\n", type);
    if(LUA_TSTRING == lua_type(L, -1))
    {
        char buf[32] = {0};
        size_t len = sizeof(buf);
        memcpy(buf, lua_tolstring(L, -1, &len), sizeof(buf));
        printf("get title: %s\n", buf);
    }

    lua_close(L);
    return 0;
}

主要通过 5 步就可以获取到 title 的值:

1, lua_getglobal(L, "Global")

通过这个函数,找到名为 Global 的全局 table,如果找到则将Global 的值 压入栈顶,就是一个 table,所以我们可以通过 lua_type(L, -1) 判断栈顶对象的类型。

    if(lua_type(L, -1) != LUA_TTABLE)    
    {
        printf("can not find table: Global \n");
        lua_close(L);
        return 1;
    }

2,lua_pushstring(L, "AtmCtrl")

将要找到对象的名称压入栈顶,记住,此时字符串 "AtmCtrl" 在栈顶位置,而第一步中的 Global 值已经在 "AtmCtrl" 的下面,即 "AtmCtrl" 的 index 为 -1, Global 的值的 index 为 -2。

3,lua_gettable(L, -2)

看我们上面的翻译:把 t[k] 的值压入栈,这里的 t 指有效索引 index 指向的值,而 k 则是栈顶放的值。很明白了,其实就是把 index = -2 位置的 Global["AtmCtrl"] 的值放到原来 k 的位置(栈顶),即 k 被弹出了,如果能找到 Gloabl["AtmCtrl"],则取到的值就在栈顶了。因为 AtmCtrl 也是一个 table,所以我们还是可以这样判断:

    if(lua_type(L, -1) != LUA_TTABLE)    /* 栈顶是否是要找到类型 */
    {
        printf("AtmCtrl is not a table\n");
        lua_close(L);
        return 1;
   

4,lua_pushstring(L, "title")

5,lua_gettable(L, -2)

后面两步就是重复第 2,3 步了。最终 title 的值被放到了栈顶,所以最后我们要把栈顶的元素取出来:

    if(LUA_TSTRING == lua_type(L, -1))
    {
        char buf[32] = {0};
        size_t len = sizeof(buf);
        memcpy(buf, lua_tolstring(L, -1, &len), sizeof(buf));
        printf("get title: %s\n", buf);
    }

 总结:lua_gettable() 使用的要点是时刻在脑子里有栈的数据结构,同时要记住栈中元素的位置以及类型,这样不管元素是什么类型,才能压入正确的 key,并取得正确的 t[k] 的值。

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值