lua与C/C++交互table(lua_gettble)

引用http://blog.csdn.net/yanjun_1982/article/details/7596171

今天上班的时候和程序对一个功能的程序接口,需求是这样的:脚本代码根据配置文件生成一组中奖信息,用table来保存,然后将这个table传给程序接口,程序根据这个table中的数据向玩家显示中奖界面。很简单的一个功能,脚本这边的函数很快就写完了,然后我就琢磨着程序的接口应该怎么写,由于之前没有试过在程序接口中访问lua脚本传过来的table,所以遇到了一些麻烦,上网搜了一下相关资料,总算搞清楚了。现在就简单总结一下c/c++与lua交互中关于table的一些用法吧。

有个Lua脚本函数叫OpenAwardWindow,它是c++实现的一个接口,对应的c++函数为LuaOpenAwardWindow,它的输入参数是一个table。现在我们要解决的问题是怎么在LuaOpenAwardWindow中遍历table中的所有元素。我们知道lua是通过栈来实现和c语言的交互的,至于为什么是栈呢,以后再专门说明吧。脚本传过来的table是放在栈顶的,即栈的-1位置,我们可以用lua_istable(L, -1)来检查输入参数是否合法。lua的数据类型和c的数据类型是不一样的,它们必须用专门的函数的转换,比如lua_tonumber(L, -1)就是把栈顶的数据转为double类型,lua_tostring(L, -1)是转为带结束符的字符串类型。新手一定会说,那lua_totable(L, -1)就是转换了table类型咯^_^。如果c有table这种数据类型,那一定会有这个函数的,可惜c没有。不过在这里我有个想法,能不能用c实现一种类型,它是可以和lua的table对应的呢?这样就真的可以有lua_totable这个接口了,这样c访问table就方便多了。我们还是回到如何在c中遍历table的问题中吧。在c中,它是这样访问table中的一个元素的:

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

lua_pushnumber(L, 1);

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

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

lua_gettable(L, -2);

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

上面说的是访问table中的一个元素的方法,那要怎么样遍历table中的所有元素呢?如果table是一个以连续的整形作为key的table, 可以用下面方法:

[cpp]  view plain copy
  1. int size = lua_objlen(L,-1);//相关于#table  
  2. for(int i = 1; i <= size; i++)  
  3. {  
  4. lua_pushnumber(L, i);  
  5. lua_gettable(L, -2);  
  6. //这时table[i]的值在栈顶了  
  7. lua_pop(L, 1);//把栈顶的值移出栈,保证栈顶是table以便遍历。  
  8. };  

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

[cpp]  view plain copy
  1. lua_pushnill(L);  
  2. while(lua_next(L, -2))  
  3. {  
  4. //这时值在-1(栈顶)处,key在-2处。  
  5. lua_pop(L, 1);//把栈顶的值移出栈,让key成为栈顶以便继续遍历  
  6. }  

这里重点说明一下lua_next。它执行操作是这样的,先判断上一个key的值(这个值放在栈顶,如果是nil,则表示当前取出的是table中第一个元素的值),然后算出当前的key,这时先把栈顶出栈,将新key进栈,最后将新key对应的值进栈。这样栈顶就是table中第一个遍历到的元素的值。用完这个值后,我们要把这个值出栈,让key在栈顶以便继续遍历。当根据上一个key值算不出下一个key值时,lua_next返回0,结束循环。

今天学习了两种遍历c代码中遍历tabl的方法,让我对lua的认识又深入了许多,由于之前太懒,而且对lua源码中“乱78糟“


详细描述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, ... <--- 这里栈顶 /* ====================================================== */
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值