lua入门教程:第六章 C API 栈平衡

较为常见的是c/c++中调用lua文件,在lua中使用luaL_dofile加载lua文件,并执行lua代码。

extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "luaconf.h"
};

#include <string.h>
int main()
{
	
	int error;
	lua_State* L = luaL_newstate();
	luaL_openlibs(L);

	int ret = luaL_dofile(L, "sum_test.lua");
	if (ret != 0)
	{
		printf("%s", lua_tostring(L, -1));
	}
	
	
	lua_getglobal(L, "Sum");
	lua_pushnumber(L, 2);//第一个参数
	lua_pushnumber(L, 3);//第二个参数
	lua_pushnumber(L, 4);//第三个参数
	lua_pcall(L, 3, 2, 0);

	double sum = 0, ave = 0;
	if (lua_isnumber(L, 1))
	{
		sum = lua_tonumber(L, 1);
	}
	if (lua_isnumber(L, 2))
	{
		ave = lua_tonumber(L, 2);
	}

	lua_close(L);

    return 0;
}

lua的代码如下:

function Sum(...)
  local s=0
  local num=0     
  for k,v in pairs{...} do
    s = s + v
       num = k
  end
  return s,s/num
end
lua和c参数栈平衡

这里面涉及到一个关键的问题,就是c/c++和lua的参数是如何进行传递的。在lua的设计时采用的是栈方式的交互模式。其中lua_getglobal表示从全局变量中取出特定的变量,放到栈中,lua_pushnumber 把数据放入到栈中,经过:

lua_getglobal(L, "Sum");
lua_pushnumber(L, 2);//第一个参数
lua_pushnumber(L, 3);//第二个参数
lua_pushnumber(L, 4);//第三个参数

后,栈的情况如下所示:

lua栈情况

在进行lua_pcall(L, 3, 2, 0)后,表明函数有3个参数,2个返回值,函数调用后把之前的函数相关参数出栈,把函数返回值入栈。栈情况变为:

lua栈情况1

从栈中取出数据使用的是lua_tonumber

sum = lua_tonumber(L, 1);

从栈底开始取数据,整数从栈底开始数起,负数从栈顶开始数起。

把数据压入栈中

这里就明白了c语言和lua进行交互的时候使用的是栈,在栈的使用中需要注意的几个函数这里都有一定的前缀。

lua_pushfstring 将一个格式化字符串压入堆栈,并返回指向这个字符串的指针;

lua_pushlstring 将一个指定大小的字符串压入堆栈;

lua_pushvalue 将栈中指定索引的元素复制一份到栈顶;

对于lua_pushx的函数是指把数据压到栈中,相反的一个操作就是从栈中取出数据,使用的是lua_tox

从栈中获取数据

lua_tostring 等价于参数len=NULL时的lua_tolstring;
lua_tonumber 将给定index索引处的元素转换为double类型;

lua_tox可以指定获取栈位置的数据。

在使用栈的时候,有时候我们已经确认了某个栈位置应该是什么样类型,在使用的时候为了确认数据类型正确与否,可以使用luaL_check来进行确认。

栈的其他操作

对于栈还有如下的一些操作:

lua_pop 从栈中弹出n个元素;

lua_gettop 返回栈顶元素的索引(也即元素个数);

lua_concat 将栈顶开始的n个元素连接起来,并将它们出栈,然后将结果入栈;

lua_getfield 将t[k]压入堆栈,t由参数index指定在栈中的位置;

lua_setfield 相当于t[k]=v,t由参数index指定在栈中的位置,v是栈顶元素,改函数会将栈顶的value出栈;

lua_getglobal(L,s) 等价于 lua_getfield(L, LUA_GLOBALSINDEX, s),注意:栈中LUA_GLOBALSINDEX索引位置处是当前Lua状态机的全局变量环境。

lua_setglobal(L,s) 等价于 lua_setfield(L, LUA_GLOBALSINDEX, s);

lua_insert 移动栈顶元素到index指定的位置;

lua_remove 移除index处的元素,index之上的元素均下移一个位置;

lua_replace 将栈顶元素移到指定位置,并取代原来的元素,原先的栈顶元素弹出;

lua_next 弹出一个key,然后将t[key]入栈,t是参数index处的table;在利用lua_next遍历栈中的table时,对key使用lua_tolstring尤其需要注意,除非知道key都是string类型。

lua_objlen 返回index处元素的长度,对string,返回字符串长度;对table,返回"#"运算符的结果;对userdata,返回内存大小;其它类型返回0;

luaL_checkstack 增加栈大小(新增sz个元素的空间),如果grow失败,引发一个错误,msg参数传递错误消息。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

go2coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值