lua中得栈

若是你看了LUA的文档,那么就应该很清楚LUA与C交互数据时都是用到LUA中所谓的stack。那么当我调用lua_open函数以后栈是什么样的呢?空的(luaopen_base等会往栈上加进一些东西)。那么至于如何操做栈上的数据,我想官方文档上已经说得很清楚了,不过最初我对于栈的顺序有一些迷糊,因此就说说这个。如今假如我有以下的一段代码: api

代码:
lua_State* L = lua_open();
lua_pushnumber( L, 211 );
lua_pushnumber( L, 2222 );
lua_newtable( L );
lua_close( L );



那么当执行完lua_newtable以后栈上有三个元素,大体就是这样: 

211 
222 
table 

如今211是第一个元素,index为1,不过LUA也能够用负数来表示,那么如今他是多少? 

index -index value 
1 -3 211 
2 -2 222 
3 -1 table 

嗯,很简单,再看看若是咱们要设置一个TABLE的值怎么作?文档中说用lua_settable或是lua_rawset(这二者有什么区别应该和这里说的无关),它们参数意义、以及准备工做都同样,-1是值,-2是键值 
lua_settable( lua_state*, int ) 
第一个参数是要操做的脚本环境,第二个则是要操做的表在栈上的位置 
通常的写法多是这样 函数

代码:
// 代码A
lua_getglobal( L, "myTable" );   // 获取要设置值的table
lua_pushstring( L, "hp" );         // "hp"在栈上的位置为-1
lua_pushnumber( L, 211 );          // "hp"在栈上的位置变为-2,而211则是-1
lua_settable( L, -3 );               // 值被正确的设置到全局变量(表)的myTable中


若是我是想把hp这个值设置到全局表中呢?通常经过调用lua_setglobal宏 lua

代码:
lua_pushnumber( L, 211 );
lua_setglobal( L, "hp" );


就这么简单,不过咱们来看看lua_setglobal这个宏 spa

代码:
#define lua_setglobal(L,s)    /
   (lua_pushstring(L, s), lua_insert(L, -2), lua_settable(L, LUA_GLOBALSINDEX))


这么看来实际上咱们上面的代码被替换成了 code

代码:
lua_pushnumber( L, 211 );
lua_pushstring( L, "hp" );
lua_insert( L, -2 );         // 这一步看上去或许比较诡异,其实是把-1的值放到lua_insert的第二个参数所指的位置,而后这个位置后面的参数往上移
                               //这里实际上最终结果就是-1和-2对调,但从逻辑上并非对调
lua_settable( L, LUA_GLOBALSINDEX );         // 这里为何不用lua_rawset?我认为是有缘由的^@^



将上面的代码与代码A结合起来看,在lua_settable时index值不一样,而它作的工做是若是发现index是LUA_GLOBALSINDEX 那么就取出全局表(还有一个LUA_REGISTERINDEX,相似),不然从stack上取元素,固然,这个栈位置取出的不是一个table就会失败。因此代码A中指定的是-3是刚从全局表中取出的myTable表(这里假设他是一个table),上面的代码片断则是取出的全局表。因此lua_settable的index是什么值均可以,只要它指向的是一个table 

实际上lua中与c的接口也就主要在栈的操做上,基本上你在写一个lua与C结合的程序时你最最须要作的工做就是明白你当前栈上有什么元素以及它们的位置。我通常会在纸上画出他们的位置,若是你熟了,对于几句在一块儿有关联的lua调用则能够很快的看出栈的变化。好比lua_gettable/lua_rawget 接口

代码:
lua_pushstring( L, "hp" );
lua_gettable( L, LUA_GLOBALSINDEX );


只看第一句,栈顶是一个字符串,但两句放在一块儿,最终栈顶是一个全局表上一个名为hp的实际值 文档

代码:
lua_pushstring( L, "hp" );
lua_pushnumber( L, 211 );
lua_settable( L, LUA_GLOBALSINDEX );


不管第二句pushnumber仍是pushvalue,pushstring什么的,最终这三句执行以后对于栈来讲是没有任何变化的,由于lua_settable/lua_rawset会移走-1和-2 

总之,对于栈的变化,在看一个函数的文档时先看它参数又须要栈上那些位置的元素并正确设置栈上的值,看清楚他会取栈上那些位置的元素做为这个lua api调用的使用并为之把正确的值放到栈上,最后注意函数完成以后会清除/移走那些位置的元素,我想应该就没什么问题了字符串

相关文章
相关标签/搜索