让我们看看下面例子C++调用LUA函数的例子栈的使用情况
#include "stdafx.h"
int main()
{
//新建一个lua状态
lua_State *pLua = luaL_newstate();
if( nullptr == pLua )
{
return 0;
}
//得到初始化栈大小
printf( "初始化栈大小:%d\n", lua_gettop( pLua ) );
//打开所有功能库
luaL_openlibs( pLua );
//加载脚本
luaL_dofile( pLua,"test.lua" );
//将脚本中的Add函数入栈
int ret = lua_getglobal( pLua, "Add" );
if( 0 == ret )
{
return 0;
}
printf( "栈大小:%d\n", lua_gettop( pLua ) );
//函数参数从右到左入栈a = 1, b = 2
lua_pushnumber( pLua, 1 );
lua_pushnumber( pLua, 2 );
printf( "栈大小:%d\n", lua_gettop( pLua ) );
//lua_pcall会调用函数并自动清除上面和函数有关的栈
//成功调用后会将返回值从右到左入栈
lua_pcall( pLua, 2, 3, 0 );
printf( "调用函数后栈大小:%d\n", lua_gettop( pLua ) );
int sum = lua_tonumber( pLua, 1 );
int a = lua_tonumber( pLua, 2 );
int b = lua_tonumber( pLua, 3 );
printf( "sum:%d a:%d b:%d\n", sum, a, b );
//手动清空所有栈
lua_pop( pLua, -1 );//或lua_settop( pLua, 0 );
printf( "栈大小:%d\n", lua_gettop( pLua ) );
lua_close( pLua );
pLua = nullptr;
return 0;
}
test.lua脚本:
Add = function( a, b )
return a + b, a, b
end
输出结果:
2.lua_gettop()函数
该函数返回当前lua状态栈的大小
3.lua_pushxxxx()类函数
该函数往栈中添加栈数据
4.lua_pop()函数
该函数表示从当前lua状态栈中弹出几个元素
如lua_pop( pLua, 2 )表示从栈顶弹出2个元素
当第二个参数填入-1时弹出所有元素即lua_pop( pLua, -1 )
5.lua中索引index的表示方法
在使用下面的函数前必须弄懂lua中索引的表示方法
如果我们使用lua_pushnumber依次添加3个数分别1,2,3
则栈的结构为:
[3] ( 访问index为:-1 或者 3 )
[2] ( 访问index为:-2 或者 2 )
[1] ( 访问index为:-3 或者 1 )
也就是说我们要访问栈顶元素3可以使用-1或者栈大小即可访问即:
lua_tonumber( pLua, -1 ) 和 lua_tonumber( pLua, 3 )都是访问相同的元素
lua_tonumber( pLua, -2 ) 和 lua_tonumber( pLua, 2 )都是访问相同的元素
lua_tonumber( pLua, -3 ) 和 lua_tonumber( pLua, 1 )都是访问相同的元素
使用负索引从-1开始访问栈顶后面依次-1即可访问其他元素
使用正索引从栈大小开始访问栈顶后面依次-1即可访问其他元素
6.lua_settop()函数
该函数用来指定哪一个索引作为栈顶元素
在指定了新的栈顶元素之前的元素都将被移除栈
即栈结构:
[3] ( 访问index为:-1 或者 3 )
[2] ( 访问index为:-2 或者 2 )
[1] ( 访问index为:-3 或者 1 )
我们使用lua_settop( pLua, -1 )无变化因为-1这个索引本来就是栈顶索引
使用lua_settop( pLua, -2 )即-2这个元素作为新栈顶则以前-1元素值为3的旧栈顶被移除
此时栈结构:
[2] ( 访问index为:-1 或者 2 )
[1] ( 访问index为:-2 或者 1 )
如果我们一开始就使用lua_settop( pLua, -3 )则
栈结构为:
[1] ( 访问index为:-1 或者 1 )其他两个被弹出
特殊情况lua_settop( pLua, 0 )移除所有栈元素同lua_pop( pLua, -1 )效果一样
其实lua_pop就是对lua_settop封装的宏而已
最后lua_settop使用正或者负索引都是可以的,不建议lua_pop使用负索引, lua_pop( pLua, -1 ) 这种
只是特殊情况,因为它的第二个参数按道理应该是个数而不是索引容易发生意想不到的情况
为了加深理解使用下面代码自己调整lua_settop来观察:
lua_pushnumber( pLua, 1 );
lua_pushnumber( pLua, 2 );
lua_pushnumber( pLua, 3 );
lua_settop( pLua, 1 );
int a = lua_tonumber( pLua, -1 );
int b = lua_tonumber( pLua, -2 );
int c = lua_tonumber( pLua, -3 );
访问不存在的元素会返回0