Lua C api 中让人头痛的栈与table传递
来源:互联网 发布:海上灵光淘宝 编辑:程序博客网 时间:2024/06/06 01:14
在Lua对C的api中有两个知识点非常重要,而且这两个知识点也是很容易导致程序出错。
1.栈的使用
其中要先看明白以下这篇参考文章:
Lua推栈
以上已经好明确的说明的栈的应用,但栈这种东西在代码中是无形,你根本就看不见,也无法通过log输出栈内的情况
所以要更好的理解这种栈的应用,需要就是代码实践加令人印象深刻的叙述了。
我们直接入正题,来理解Lua C api中栈的应用。
一、单个参数的传递
首先我们在Lua中注册一个C类PJYCallbackMgr,其中一个方法为:
int testLuaCall(lua_State* L){ ... ... }
然后我们在Lua调用这个方法,传入各种值,首先我们传入一个int,例如:
<pre name="code" class="java">PJYCallbackMgr.testlua(1007)
那么在C层我们怎么获取这个1007的值呢?
在这之前我们先来看看,Lua调用这个方法之后,就会1007这个值压入到堆栈lua_State中,
因为只有一个值,所以此时lua_State的堆栈状态应该是这样的:
// 说明 栈内容 排序 排序
// 栈顶/栈底 1007 -1 1
因为只有一个值,所有这个1007,既是栈底也是栈顶,注意两个不同方法的排序方式。排序方式不明白,请参考上面的文章。
因此我们在C层要做的事情就是通过这个 lua_State* L来获取栈中的值。
代码:
//首先检查一下是否一个number luaL_checktype(L, 1, LUA_TNUMBER);int luavalue= lua_tonumber(L,-1);CCLOG("luavalue = %d", luavalue);
你会看到输出:
二、多个参数的传递
在Lua中我们传入多个参数给C类,如下:
<span style="font-size:14px;"> PJYCallbackMgr.testlua(1007,"numberA","numberB")</span>
那么我们在C类中如何获取?
------------------------此时栈中的内容应该如下------------------- 说明 栈内容 排序 排序 栈顶是 numberB -1 3 numberA -2 2 栈低是 1007 -3 1首先检查一下是否一个number 如果此时还是先检查序号1的index栈内容 不会报错 以luaL_checktype(L, 1, LUA_TNUMBER);//根据以上的栈 我们轻易地获取其值if (lua_isstring(L, -1)){std::string numberBstring = lua_tostring(L, -1);const char* numberB = numberBstring.c_str();CCLOG("numberB = %s", numberB);}if (lua_isstring(L, -2)){std::string numberAstring = lua_tostring(L, -2);const char* numberA = numberAstring.c_str();CCLOG("numberA = %s", numberA);}if (lua_isnumber(L, -3)){int luanumber = lua_tonumber(L, -3);CCLOG("luanumber = %d", luanumber);}
你会看到输出:
2.table的传递和标记
table是Lua中最重要的一环,很多Lua中的方法原原理 , 结构原理都会用到table。
为了更好的了解table的传递,需要先阅读以下的参考文章。
如何在Lua与C/C++之间实现table数据的交换
一、简单table
那么我们就在Lua中传递一个table到C中:
local tableA = {1007,"numberA","numberB"} PJYCallbackMgr.testlua(tableA)
在C中:注意看注释
//------------------------此时栈中的内容应该如下-------------------// 说明 栈内容 排序 排序// 栈低/栈顶 table -1 1luaL_checktype(L, 1, LUA_TTABLE);//检查栈顶是否一个tablelua_pushnumber(L, 1);//先向栈中压入一个数字 为何要压入一个数字呢? //------------------------此时栈中的内容应该如下-------------------// 说明 栈内容 排序 排序// int 1 -1 2// 栈低 table -2 1lua_gettable(L, -2);//获取table中的第一个元素value 并把这个value放到栈顶//------------------------此时栈中的内容应该如下-------------------// 说明 栈内容 排序 排序// int 1007 -1 2// 栈低 table -2 1if (lua_isnumber(L, 2)){ //再获取栈顶的1007 valueint luanumber = lua_tonumber(L, 2);CCLOG("luanumber = %d", luanumber);}//然后出栈 这一步很重要,同样地我们也应该在上面多参数传递时,获取完栈顶数值之后,出栈,//让C语言保持多栈顶的控制,而不改变整个栈//把栈顶的数值弹出lua_pop(L, 1);//------------------------此时栈中的内容应该如下-------------------// 说明 栈内容 排序 排序// 栈低 table -1 1 //得到这个原始干净的栈之后 就会继续获取下面的值lua_pushnumber(L, 2);lua_gettable(L, -2);if (lua_isstring(L, -1)){std::string luastring = lua_tostring(L, -1);const char* numberA = luastring.c_str();CCLOG("numberA = %s", numberA);}lua_pop(L, 1);//同理可以得到lua_pushnumber(L, 3);lua_gettable(L, -2);if (lua_isstring(L, -1)){std::string luastring = lua_tostring(L, -1);const char* numberB = luastring.c_str();CCLOG("numberA = %s", numberB);}lua_pop(L, 1);
由以上代码,我们获取到Lua中tableA中的元素值,但我们获取table值的时候,为何要先在栈中push一个数字number呢?而上面单个或多个参数传递的就不需要?
首先,我们先来了解一下lua_gettable(L, -2);这个函数先。
这个函数的意思是:以栈顶的元素为下标,在-2位置上的table表中,获取对应下标的元素value,然后把这个下标弹出栈,再把元素value放置栈顶上。
从上面代码可知,我们先push了一个1进去,然后就根据这个1,去table表中找下标为1的元素,即为table[1], 根据lua定义,table[1]就是第一个元素的值。
local tableA = {1007,"numberA","numberB"} PJYCallbackMgr.testlua(tableA) print(tableA[1]);
因此,我们在获取table元素值的时候,需要先push一个栈顶值进去作为table里面的key,在获取key对应的value。
二、复杂的table
我们再往C中传递一个复杂的table看看,再C中如何获取。
local payinfo={roleid="" ,money=0,productName="",callBackStr="", gameGold="",rate=0} PJYCallbackMgr.testlua(payinfo)
参考上面的文章,和结合上文,我们很容易就可以获取roleid等各个key对应的值,先push一个key对应的string,进去栈中,然后同个gettable获取对应的值
但这个方法往往要对栈进行push和pop,稍不注意就出错。所以我们可以利用C api中另一个方法更直观地获取这种table中的值。
luaL_checktype(L, 1, LUA_TTABLE);//检查栈顶是否一个tablelua_getfield(L,-1,"roleid");//如果是table 取出它的roleid值放到栈顶 此时的栈// 说明 栈内容 排序 排序// 栈顶是 roleid_value -1 2// 栈低是 table -2 1if (lua_isstring(L,-1)){std::string luastring = lua_tostring(L, -1);const char* lualog = luastring.c_str();CCLOG("roleid = %s", lualog);}//此时roleid_value已经在栈顶 并没有出栈//获取moneylua_getfield(L, 1, "money");if (lua_isnumber(L,-1)){int money = lua_tonumber(L, -1);CCLOG("money = %d", money);}//此时money_value已经在栈顶 并没有出栈 所以要用序号1来index栈低的tablelua_getfield(L, 1, "productName");if (lua_isnumber(L, -1)){std::string productNamestring = lua_tostring(L, -1);const char* productName = productNamestring.c_str();CCLOG("productName = %s", productName);}//此时productName_value已经在栈顶 并没有出栈 所以要用序号1来index栈低的table//透传字段lua_getfield(L, 1, "callBackStr");if (lua_isnumber(L, -1)){std::string callBackStrstring = lua_tostring(L, -1);const char* callBackStr = callBackStrstring.c_str();CCLOG("callBackStr = %s", callBackStr);}//主要交易货币名称lua_getfield(L, 1, "gameGold");if (lua_isnumber(L, -1)){std::string gameGoldstring = lua_tostring(L, -1);const char* gameGold = gameGoldstring.c_str();CCLOG("gameGold = %s", gameGold);}//获取moneylua_getfield(L, 1, "rate");if (lua_isnumber(L, -1)){int rate = lua_tonumber(L, -1);CCLOG("rate = %d", rate);}
以上代码关键在于lua_getfield(L, 1, "productName");它提供了我们在table中找到key对应的value值,并把value值放置栈顶的方法。
lua_getfield(L,table在该栈的索引,key的名称)
这种方法更直观地获取一个table中的元素,但由于没有进行清栈行为,因此会存在内存的问题,所以改方法最好就用于元素少的时候使用。
- Lua C api 中让人头痛的栈与table传递
- 【转】关于lua table的C API
- Lua笔记-关于lua table的C API
- Lua笔记-关于lua table的C API
- Lua笔记-关于lua table的C API
- 在C/C++中 用C API遍历lua table
- C函数传递一个table给lua代码中使用。
- lua与c++的相互调用、C/C++修改Lua中Table的内容
- c遍历lua中table的方法
- Lua编程中遇到的table类型传递引用问题
- lua 与的C api交互操作
- C++与Lua交互的C API
- Lua 中栈操作的C API示例
- Lua 学习笔记:C API 遍历 Table
- Lua 学习笔记:C API 遍历 Table
- LUA中C API的熟悉实例
- 让人头晕的const
- 让人头疼的QTP
- 内存分析工具 MAT 的使用
- oracle 级联删除
- myeclipse中导入项目,中文出现乱码
- DATE_FORMAT函数用法
- JS UrlEncode UrlDecode
- Lua C api 中让人头痛的栈与table传递
- 黑马程序员——Java基础——继承之内部类(四)
- opencv for android (环境搭建篇)
- 【小松教你手游开发】【面试必读(编程基础)】转载一篇优秀的c#泛型理解
- Android手机存储器分类
- MFC的图片控件的使用(图片适应控件大小并不失真)
- sqlmap 使用测试初级教程(实际已测试 -版本1.0)
- MySQL存储引擎
- 自定义卫星菜单CustomArcMenu