Lua – C++堆栈操作分析

    Lua和C/c++语言通信的主要方法是一个无处不在的虚拟栈。栈的特点是先进后出。

    Lua堆栈就是一个struct,堆栈索引的方式可是是正数也可以是负数,区别是:正数索引1永远表示栈底,负数索引-1永远表示栈顶

    QQ图片20180820171309

    后续博客将更多实践lua在开发环境的应用。当前主要实践lua与C++之间数据和函数之间的调用,同时查看lua虚拟栈的操作过程。

    luac.lua

    name = "luac"
    version = 1
    me = { name = "xchen", gender = "female" }
    function add(a,b)
     return a+b
    end
    
    print("AddNumber from C----"..AddNumber(1,2))

    main.cpp

    定义一个查看lua虚拟栈的函数,用来实时查看栈的信息

    static void stackDump(lua_State* L)
    {
     cout << "\n-------------- dump lua stack start--------------" << endl;
     int i = 0;
     int top = lua_gettop(L); //获取栈顶下标
     for (i = top; i <= top; --i)
     {
     if (i == 0)
     {
     break;
     }
     int t = lua_type(L, i); //获取栈上数据类型
     switch (t)
     {
     case LUA_TSTRING:
     {
     printf("|INDEX='%d','LUA_TSTRING=%s'|\n", i,lua_tostring(L, i));
     }
     break;
     case LUA_TBOOLEAN:
     {
     printf("|INDEX='%d','LUA_TBOOLEAN=%s'|\n", i,lua_toboolean(L, i) ? "true" : "false");
     }
     case LUA_TNUMBER:
     {
     printf("|INDEX='%d','LUA_TNUMBER=%g'|\n", i,lua_tonumber(L, i));
     }
     break;
     default:
     {
     printf("|INDEX='%d','DEFAULT=%s'|\n", i,lua_typename(L, t));
     }
     break;
     }
     }
     cout << "-------------- dump lua stack end --------------\n" << endl;
    }
    

    1.lua调用c++函数接口

    int add(lua_State* L)
    {
     stackDump(L); //查看堆栈信息
     int a = lua_tonumber(L, -1);
     int b = lua_tonumber(L, -2);
     int sum = a + b;
     lua_pushnumber(L, sum);
     stackDump(L);
     return 1;
    }
    void luac()
    {
     lua_State* lua_state = luaL_newstate();
     luaL_openlibs(lua_state);
     lua_register(lua_state, "AddNumber", add);
    //注册C++函数指针和对应在lua调用的key-名字
     int ret = luaL_dofile(lua_state, "luac.lua");
    ...
    }
    

    QQ图片20180820162635


    2.读取lua文件中的数据

    void luac()
    {
    ...
     //读取字符串
     lua_getglobal(lua_state, "name"); //入栈name
     std::cout << "name = " << lua_tostring(lua_state, -1) << std::endl;
     stackDump(lua_state);
    
     //读取数字
     lua_getglobal(lua_state, "version");
     std::cout << "version = " << lua_tonumber(lua_state, -1) << std::endl;
     stackDump(lua_state);
    
     //读取表
     lua_getglobal(lua_state, "me");
     if (!lua_istable(lua_state, -1))
     {
     std::cout << "error:it is not a table" << std::endl;
     }
     stackDump(lua_state);
    ...
    }
    

    QQ图片20180820163050


    3.读取lua文件中table的数据
    void luac()
    {
    ...
     //读取表中的字段
     lua_getfield(lua_state, -1, "name");
     std::cout << "student name = " << lua_tostring(lua_state, -1) << std::endl;
     stackDump(lua_state);
    
     lua_getfield(lua_state, -2, "gender");
     std::cout << "student gender = " << lua_tostring(lua_state, -1) << std::endl;
     stackDump(lua_state);
    ...
    }

     6


    4.修改lua文件中table中的数据

    void luac()
    {
    ...
     //修改表中的字段
     lua_pushfstring(lua_state, "007");
     stackDump(lua_state);
     lua_setfield(lua_state, -4, "name");
     stackDump(lua_state);
    
     //读取修改后的表中的字段
     lua_getfield(lua_state, -3, "name");
     std::cout << "student newname = " << lua_tostring(lua_state, -1) << std::endl;
     stackDump(lua_state);
    ...
    }

    4


    5.读取lua文件中函数
    void luac()
    {
    ...
     //读取函数
     lua_getglobal(lua_state, "add");
     stackDump(lua_state);
     lua_pushnumber(lua_state, 15);
     stackDump(lua_state);
     lua_pushnumber(lua_state, 5);
     stackDump(lua_state);
     lua_pcall(lua_state, 2, 1, 0);//2-参数格式,1-返回值个数,调用函数,函数执行完,会将返回值压入栈
     std::cout << "5 + 15 = " << lua_tonumber(lua_state, -1) << std::endl;
     stackDump(lua_state);
    ...
    }

    7


    lua与C++的交互都是在lua的虚拟栈中操作,lua中的值都是由lua虚拟机去管理,整个过程类似,C++想要什么,就会放到lua的虚拟栈上, 然后lua提供了特定的API给C++操作,lua的中的数据的声明周期也是归lua去管理,所以也必须是有lua去创建这些数据。

    1.C++想要获取lua文件中的某个值时,本身lua是一个table类型,key=value的键值结构,那么C++把key放到lua的栈顶,以便让lua可以操作

    2.lua从堆栈(栈顶)获取到key,此时栈就会再次变为空

    3.lua拿着这个key去lua的全局表(_G)查找key对应的value

    4.全局表根据查询返回value给lua,lua把取得的value放入到堆栈(栈顶)

    5.C++就可以从lua堆栈(栈顶)上取得value.

    通过以上的代码示例和堆栈相关信息,就可以知道整个过程堆栈的入栈和出栈过程了!

    有帮助就分享一下吧!

    转载请注明:少狼 – 敬畏知识的顽皮狗 » Lua – C++堆栈操作分析

    喜欢 1

*

还没有人抢沙发呢~