之前一直没理清lua_gettable和lua_settable的使用,今天理清了,顺便就做下笔记了。
1.lua_gettable
void lua_gettable (lua_State *L, int index);

t[k] 值压入堆栈,这里的 t 是指有效索引 index 指向的值,而 k 则是栈顶放的值。这个函数会弹出堆栈上的 key,把结果放在栈上相同位置。

下面举个例子:

// 将一个key放到栈顶,这个key为1。如果你的key是字符串,那就用lua_pushstring。

lua_pushnumber(L, );

// table一开始是在栈顶,即-1处的,但上面的语句压入了一个值,栈顶变-2了。

// lua_gettable的作用就是以栈顶的值作为key来访问-2位置上的table。

lua_gettable(L, -);

这时table中的第1个元素的值就放到栈顶了,你想怎么使用就怎么使用吧。

获取table元素:

* 将元素的key压入到栈中,用 lua_gettable(Lua_state,index)

* 对于字符串索引,可以用lua_getfield(Lua_state,index,key)来直接获取,

  如:lua_getfield(stack, -1, "loaded");等价于 lua_pushstring(L,"loaded") lua_gettable(L,-2);

上面说的是访问table中的一个元素的方法,那要怎么样遍历table中的所有元素呢?

1)如果table是一个以连续的整形作为key的table, 可以用下面方法:

int size = lua_objlen(L,-);//相关于#table
for(int i = ; i <= size; i++)
{
lua_pushnumber(L, i);
lua_gettable(L, -);
//这时table[i]的值在栈顶了
lua_pop(L, );//把栈顶的值移出栈,保证栈顶是table以便遍历。
};

2)如果table中的key是任意值呢?可以用下面的方法:

lua_pushnill(L);
while(lua_next(L, -))
{
//这时值在-1(栈顶)处,key在-2处。
lua_pop(L, );//把栈顶的值移出栈,让key成为栈顶以便继续遍历
}

这里重点说明一下lua_next。

它执行操作是这样的,以栈顶元素为key,先判断上一个key的值(这个值放在栈顶,如果是nil,则表示当前取出的是table中第一个元素的值),然后得到当前的key和value。

这时先把栈顶出栈,将新key进栈,后将value进栈。这样栈顶就是table中第一个遍历到的元素的值。用完这个值后,我们要把这个值出栈,让新key在栈顶以便继续遍历。当根据上一个key值算不出下一个key值时(其实这时候key的是多少并不重要,只要不为nil就行,因为为nil会返回table的第一个元素),lua_next返回0,结束循环。

2.lua_settable
void lua_settable (lua_State *L, int index);

作一个等价于 t[k] = v 的操作, 这里 t 是一个给定有效索引 index 处的值, v 指栈顶的值, 而 k 是栈顶之下的那个值。

这个函数会把键和值都从堆栈中弹出。

其实这个解释的意思就是,lua_settable 会把栈顶作为value,栈顶的下一个作为key设置到index指向的table,最后把这两个弹出弹出栈,这时候settable完成。

3.lua_next
int lua_next (lua_State *L, int index);

从栈上弹出一个 key(键),然后把索引指定的表中 key-value(健值)对压入堆栈(指定 key 后面的下一 (next) 对)。如果表中以无更多元素,那么lua_next 将返回 0 (什么也不压入堆栈)。

典型的遍历方法是这样的:

     /* table 放在索引 't' 处 */
lua_pushnil(L); /* 第一个 key */
while (lua_next(L, t) != ) {
/* 用一下 'key' (在索引 -2 处) 和 'value' (在索引 -1 处) */
printf("%s - %s\n",
lua_typename(L, lua_type(L, -)),
lua_typename(L, lua_type(L, -)));
/* 移除 'value' ;保留 'key' 做下一次迭代 */
lua_pop(L, );
}

在遍历一张表的时候,不要直接对 key 调用 lua_tolstring ,除非你知道这个 key 一定是一个字符串。调用 lua_tolstring 有可能改变给定索引位置的值;这会对下一次调用 lua_next 造成影响。

最后我们以一段c调用lua的loaded表并且设置符合某个规章的key将它的value设置为nil,为列:

 ua_getglobal(stack, "package");                         /* L: package,获得package,在栈定 */
lua_getfield(stack, -, "loaded"); /* L: package loaded,获得表,在栈顶*/
lua_pushnil(stack); /* L: package loaded nil */
while ( != lua_next(stack, - ) ) /* L: package loaded, key, value,上一个栈顶为nil,弹出nil,获得表的第一个key和value,压入栈 */
{
//CCLOG("%s - %s \n", tolua_tostring(stack, -2, ""), lua_typename(stack, lua_type(stack, -1)));
std::string key=tolua_tostring(stack, -, ""); /*这时候栈顶得下一个,是key*/
std::string tableKey =key; /*下面是对key的一段处理*/
int found = tableKey.rfind(".lua");
if (found!=std::string::npos)
tableKey = tableKey.substr(,found);
tableKey=replaceAll(tableKey,".","/");
tableKey=replaceAll(tableKey,"\\","/");
tableKey.append(".lua");
found = fileName.rfind(tableKey);
if ( == found || ( found!=std::string::npos && fileName.at(found-) == '/'))
{
lua_pushstring(stack, key.c_str()); /*package loaded, key, value,newkey, 将key,压入栈顶*/
lua_pushnil(stack); /* pakage,loaded(table)(-5),key(-4),value(-3),key(-2),nil(-1)*/
if (lua_istable(stack, -)) /*判读栈顶往下第五个是不是table*/
{
/*结果将key对应的值置为nil*/
lua_settable(stack, -);/*pakage,loaded(table),key,value, 将栈顶两个元素作为key和value设置给table,弹出栈顶两个元素*/
}
}
lua_pop(stack, ); /*pakage,loaded(table),key 弹出value,留下key作为下一个next*/
}
lua_pop(stack, ); /*栈平衡*/

Lua C Api lua_gettable 、lua_settable 、lua_next 使用详解的更多相关文章

  1. Lua中强大的元方法__index详解

    今天要来介绍比较好玩的内容:__index元方法 我是备胎,记得回头看看 咳咳,相信每一位女生都拥有或者不知不觉中拥有了一些备胎,啊!当然,又或许是成为过别人的备胎. 没有备胎的人,就不是完整的人生. ...

  2. Java数据持久层框架 MyBatis之API学习十(Logging详解)

    对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...

  3. Lua中的模块与module函数详解

    很快就要开始介绍Lua里的“面向对象”了,在此之前,我们先来了解一下Lua的模块. 1.编写一个简单的模块 Lua的模块是什么东西呢?通常我们可以理解为是一个table,这个table里有一些变量.一 ...

  4. API联调神器PostMan使用详解

    简介 创建 + 测试:创建和发送任何的HTTP请求,请求可以保存到历史中再次执行 Organize:使用Postman Collections为更有效的测试及集成工作流管理和组织APIs docume ...

  5. Queue API的几种实现详解

    目录 Queue API的几种方法的使用 ArrayBlockingQueue原理及源码解析 ArrayBlockingQueue的成员变量 ArrayBlockingQueue的offer和put方 ...

  6. 【地图API】收货地址详解2

    上次讲解的方法是: 在地图中心点添加一个标注,每次拖动地图就获取地图中心点,再把标注的位置设置为地图中心点.可参考教程:http://www.cnblogs.com/milkmap/p/6126424 ...

  7. Lua中ipairs和pairs的区别详解

    迭代器for遍历table时,ipairs和pairs的区别: 区别一:ipairs遇到nil会停止,pairs会输出nil值然后继续下去 区别二: , b = , x = , y = , " ...

  8. Java多线程:实现API接口创建线程方式详解

    先看例子: /**实现Runnable接口创建线程步骤: * 1.创建一个实现Runnable接口的类 * 2.重写Runnable类中抽象的run()方法 * 3.创建实现类的对象 * 4.声明Th ...

  9. restful风格详解

    一.概念 RESTful架构,就是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用. REST这个词,是Roy Thomas Fielding在他 ...

随机推荐

  1. AI 人工智能 探索 (五)

    我们把做好的 角色 拖到 内存池,如图所示,这样我们可以动态生成角色并给予他 寻路目标. //逗留碰撞 void OnTriggerStay(Collider other) { if (other.t ...

  2. Windows 2003】利用域&&组策略自动部署软件

    Windows 2003]利用域&&组策略自动部署软件 转自 http://hi.baidu.com/qu6zhi/item/4c0fa100dc768613cc34ead0 ==== ...

  3. Vacations

    Vacations Vasya has n days of vacations! So he decided to improve his IT skills and do sport. Vasya ...

  4. 贝塞尔曲线 & CAShapeLayer & Stroke 动画 浅谈

    转载自:http://46aae4d1e2371e4aa769798941cef698.devproxy.yunshipei.com/qiaoqiaoqiao2014/article/details/ ...

  5. 直接拿来用!最火的iOS开源项目(一)

    直接拿来用!最火的iOS开源项目(一) 发表于2013-06-05 10:17| 39373次阅读| 来源CSDN| 100 条评论| 作者唐小引 iOS开源项目GitHub移动开发最受欢迎的开源项目 ...

  6. mutilple output reduce cannot write

    package org.lukey.hadoop.classifyBayes; import java.io.BufferedReader; import java.io.IOException; i ...

  7. Qt5:Qt文件操作类 QFile

    在QT中,操作文件一般不使用C++提供的文件操作类 , 因为操作文件的时候,要用到C++提供的 string 类,而在QT中使用的是Qt自己实现的一个string类 QString .在Qt中使用C+ ...

  8. python标准库-日志logging

    1.模块级别 先看一下logging模块的日志级别特点,共分6个等级. 可以手工设置当前日志的默认等级(warn),当日志输出的等级高于默认等级时,日志输出到屏幕,否则不输出. #!/usr/bin/ ...

  9. 一道变态的js题

    一道腾讯js面试题 题目如下: f = function() {return true;}; g = function() {return false;}; (function() { if (g() ...

  10. ZjDroid工具介绍及脱壳详细示例

    前提条件: 1.Root手机一部 2.需要通过Xposed installer(http://dl.xposed.info/latest.apk)安装Xposed Framework; 一.ZjDro ...