Lua堆栈就是一个struct,堆栈索引的方式可是是正数也可以是负数,区别是:正数索引1永远表示栈底,负数索引-1永远表示栈顶
Lua – C++堆栈操作分析
Lua和C/c++语言通信的主要方法是一个无处不在的虚拟栈。栈的特点是先进后出。
|
后续博客将更多实践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"); ... }
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); ... }
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);
...
}
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);
...
}
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);
...
}
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++堆栈操作分析
还没有人抢沙发呢~