• 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 脚本如下:

    1. --定义了一个全局表
    2. COM = {}
    3. --定义了一个局部函数
    4. local function add(a, b)
    5. print("a = "..a);
    6. print("b = "..b);
    7. return a + b;
    8. end
    9. COM =
    10. {
    11. width = 2550,
    12. myAdd = add,
    13. }
    14. ATMCtrl = {
    15. channalNum = 8,
    16. title = "ATM machine"
    17. }
    18. Global = {
    19. AtmCtrl = ATMCtrl
    20. }

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

    1. #include
    2. #include
    3. #include
    4. #ifdef __cplusplus
    5. extern "C" {
    6. #include
    7. #include
    8. #include
    9. }
    10. #endif
    11. int main()
    12. {
    13. lua_State *L = luaL_newstate();
    14. luaL_openlibs(L);
    15. if(luaL_loadfile(L, "init.lua"))
    16. {
    17. printf("load file: hello.lua faild...\n");
    18. lua_close(L);
    19. return 1;
    20. }
    21. lua_pcall(L, 0, 0, 0); /* 前面这几步都基本固定 */
    22. lua_getglobal(L, "Global"); /* 先找到表 */
    23. if(lua_type(L, -1) != LUA_TTABLE)
    24. {
    25. printf("can not find table: Global \n");
    26. lua_close(L);
    27. return 1;
    28. }
    29. lua_pushstring(L, "AtmCtrl"); /* 将要找的关键字入栈 */
    30. int type = lua_gettable(L, -2); /* 如果找到则将 AtmCtrl 的值入栈,即放到栈顶 */
    31. if(lua_type(L, -1) != LUA_TTABLE) /* 栈顶是否是要找到类型 */
    32. {
    33. printf("AtmCtrl is not a table\n");
    34. lua_close(L);
    35. return 1;
    36. }
    37. lua_pushstring(L, "title");
    38. type = lua_gettable(L, -2);
    39. printf("get type: %d\n", type);
    40. if(LUA_TSTRING == lua_type(L, -1))
    41. {
    42. char buf[32] = {0};
    43. size_t len = sizeof(buf);
    44. memcpy(buf, lua_tolstring(L, -1, &len), sizeof(buf));
    45. printf("get title: %s\n", buf);
    46. }
    47. lua_close(L);
    48. return 0;
    49. }

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

    1, lua_getglobal(L, "Global")

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

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

    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,所以我们还是可以这样判断:

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

    4,lua_pushstring(L, "title")

    5,lua_gettable(L, -2)

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

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

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

  • 相关阅读:
    【C++ Core Guidelines解析】深入理解现代C++的特性和原理
    深度学习在图像处理中的应用学习笔记
    Iceberg Flink FLIP-27实现
    Monaco Editor教程(十四):monaco中的位置区间Range类型的详细解释
    十分钟学习 TypeScript
    快进来看看!!!C语言——扫雷小游戏(递归展开无雷区)
    关于MybatisPlus使用的部分经验
    重学java 63.IO流 字节流 ④ 文件复制
    激活函数总结(三十九):激活函数补充(NFN、Hermite)
    VNC:Timed out waiting for a response from the computer
  • 原文地址:https://blog.csdn.net/tianyexing2008/article/details/126705380