Lua api(七) lua_remove/lua_replac

作者: AlbertS | 来源:发表于2016-07-04 20:00 被阅读561次

前言#

初步了解过lua的人都知道,lua和c交互式通过虚拟栈来实现的,这个栈造就了lua的神奇,那么我们今天来看看怎样直接操作这个虚拟栈,首先我们要知道c调用lua和函数是通过和struct lua_State相关的栈来交换数据的,而Lua 调用C函数用的栈是临时的,调用结束之后就被销毁了。我们下面要讲的是c调用lua的栈,我们可以通过特定的api来改变栈内数据。

内容#


lua_remove##

  • 原型:void lua_remove (lua_State *L, int index);
  • 解释: 从给定有效索引处移除一个元素, 把这个索引之上的所有元素移下来填补上这个空隙。

lua_replace##

  • 原型:void lua_replace (lua_State *L, int index);
  • 解释:把栈顶元素移动到给定位置(并且把这个栈顶元素弹出), 不移动任何元素(因此在那个位置处的值被覆盖掉)。

Usage##

  • 首先我们先新建一个文件,文件命名为removetest.lua编写如下代码:
-- 定义一个全局table
LanguagesTable = 
{
    "lua",
    "c",
    "c++",
    "java",
    "python",
}

-- 定义一个打印函数
function func_printarray()
    for index,value in pairs(LanguagesTable) do
        print("lua --> ["..index.."] = ".. value);
    end
    print("\n");
end
  • 接下来我们来编写c++调用的函数的代码如下:
    lua_State *L = lua_open();
    luaL_openlibs(L);

    luaL_dofile(L,"removetest.lua");    // 加载执行lua文件
    lua_getglobal(L, "func_printarray");// 打印一下table的内容
    lua_pcall(L, 0, 0, 0);              // 调用函数

    lua_getglobal(L,"LanguagesTable");  // 将全局表压入栈

    // 记录压栈前元素个数
    const int nPreStack = lua_gettop(L);

    // 将数组元素入栈
    for(int nIndex = 1; nIndex <= 5; ++nIndex)
    {
        lua_rawgeti(L, -1 * nIndex, nIndex);
    }
    
    // 替换元素,使用栈顶元素替换栈顶向下第3个元素
    lua_replace(L, -3);                 // -->lua_replace用法

    // 删除元素,删除栈顶元素
    lua_remove(L, -1);                  // -->lua_remove用法

    // 查询当前栈中元素个数
    const int nCurStack = lua_gettop(L);

    // 打印栈中元素
    for(int nIndex = nPreStack + 1; nIndex <= nCurStack; ++nIndex)
    {
        printf("c++ --> stack pos %d : val = %s\n", nIndex, lua_tostring(L, nIndex));
    }

    lua_close(L);                       //关闭lua环境  
  • 结果
remove.png

结论#

  • 不能用伪索引来调用lua_remove这个函数, 因为伪索引并不指向真实的栈上的位置。
  • 通过结果我们来分析一下最后的打印顺序,开始时我们将左右元素压入栈中,“lua”在栈底,“python”在栈顶,执行lua_replace(L, -3)后“python”将“c++”替换,然后栈顶的“python”被弹出,然后执行lua_remove(L, -1)后栈顶的“java”被弹出,结果借得到了“lua”、“c”、“python”的顺序。
  • 读取table的内容时一定要确保table已经被加载到栈中,我在调试的时候就有好几次因为读取了错误的文件,结果没有把正确的table加载到栈中,而导致了程序的崩溃。

相关文章

  • Lua api(七) lua_remove/lua_replac

    前言# 初步了解过lua的人都知道,lua和c交互式通过虚拟栈来实现的,这个栈造就了lua的神奇,那么我们今天来看...

  • FreeSWITCH环境Lua API参考手册

    Lua API Reference 关于 本页面提供Lua的FreeSWITCH API文档。 API Sessi...

  • Lua API (state manipulation)

    一:LUA_API lua_State* (lua_newstate)(lua_Alloc f, void* ud...

  • Lua C API

    C API 云风Blog:Lua C API 的正确用法 C读取和调用Lua文件的库:lua.h, lauxlib...

  • lua 参考手册

    api lua文档 http://lua.hust.cc/ lua port : http://www.eluap...

  • LuaC API

    Lua C APi 总结 Lua_newtable(L) 创建table并放到栈顶 lua_pushstring(...

  • 在spring-data-redis中使用lua脚本

    参考 Lua 脚本Programming in Lua api 使用 RedisScript 使用 Redi...

  • lua_newstate

    version 5.3.5 1、lua_newstate是由lstate.c提供的lua内部函数,由LUA_API...

  • Lua API (basic stack manipulatio

    一:LUA_API int (lua_gettop)(lua_State* L) 用途:返回栈顶元素的索引 由于索...

  • Lua扩展

    lua作为配置文件使用 使用LUA API分析这个文件,并获取width和height table操作lua 5....

网友评论

  • 2fb065dabb67: lua_rawgeti(L, -1 * nIndex, nIndex);
    此处,第二个参数可以换为1,反正全局表一直在栈底,直接取1不是比-1,-2,一点点往下更简洁吗?
    2fb065dabb67:@AlbertS 懂了,谢谢
    AlbertS:就这里的例子来说是可以的,这里写成表达式主要是为了适应变化的情况,比如栈底可能有n个值,这个n是从上一个函数计算出来的,那么这里就需要做适当的变化了

本文标题:Lua api(七) lua_remove/lua_replac

本文链接:https://www.haomeiwen.com/subject/tmthjttx.html