lua
2019-11-19 18:29:16

lua入门教程:C API 栈平衡

34 / 1 / 0 / 0

较为常见的是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参数传递错误消息。

PS: 如本文对您有疑惑,可加QQ:1752338621 进行讨论。

1 条评论

0
0
官方
微信
官方微信
Q Q
咨询
意见
反馈
返回
顶部