lua 与C通过c api传递table (2)
本文转自http://blog.csdn.net/a_asinceo/article/details/49907903(感谢。。。)
一、单个参数的传递
首先我们在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 1
- luaL_checktype(L, 1, LUA_TTABLE);//检查栈顶是否一个table
- lua_pushnumber(L, 1);//先向栈中压入一个数字 为何要压入一个数字呢?
- //------------------------此时栈中的内容应该如下-------------------
- // 说明 栈内容 排序 排序
- // int 1 -1 2
- // 栈低 table -2 1
- lua_gettable(L, -2);//获取table中的第一个元素value 并把这个value放到栈顶
- //------------------------此时栈中的内容应该如下-------------------
- // 说明 栈内容 排序 排序
- // int 1007 -1 2
- // 栈低 table -2 1
- if (lua_isnumber(L, 2)){ //再获取栈顶的1007 value
- int 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);//检查栈顶是否一个table
- lua_getfield(L,-1,"roleid");//如果是table 取出它的roleid值放到栈顶 此时的栈
- // 说明 栈内容 排序 排序
- // 栈顶是 roleid_value -1 2
- // 栈低是 table -2 1
- if (lua_isstring(L,-1)){
- std::string luastring = lua_tostring(L, -1);
- const char* lualog = luastring.c_str();
- CCLOG("roleid = %s", lualog);
- }
- //此时roleid_value已经在栈顶 并没有出栈
- //获取money
- lua_getfield(L, 1, "money");
- if (lua_isnumber(L,-1)){
- int money = lua_tonumber(L, -1);
- CCLOG("money = %d", money);
- }
- //此时money_value已经在栈顶 并没有出栈 所以要用序号1来index栈低的table
- lua_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);
- }
- //获取money
- lua_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中的元素,但由于没有进行清栈行为,因此会存在内存的问题,所以改方法最好就用于元素少的时候使用。
例子:
int func_return_table(lua_State *L)
{
lua_newtable(L);//创建一个表格,放在栈顶
lua_pushstring(L, "mydata");//压入key
lua_pushnumber(L,66);//压入value
lua_settable(L,-3);//弹出key,value,并设置到table里面去
lua_pushstring(L, "subdata");//压入key
lua_newtable(L);//压入value,也是一个table
lua_pushstring(L, "mydata");//压入subtable的key
lua_pushnumber(L,53);//value
lua_settable(L,-3);//弹出key,value,并设置到subtable
lua_settable(L,-3);//这时候父table的位置还是-3,弹出key,value(subtable),并设置到table里去
lua_pushstring(L, "mydata2");//同上
lua_pushnumber(L,77);
lua_settable(L,-3);
return 1;//堆栈里现在就一个table.其他都被弹掉了。
}
返回的表结构是:
{
"mydata" = 66,
"mydate2" = 77,
"subdata" =
{
"mydata" = 53
}
}
lua 与C通过c api传递table (2)的更多相关文章
- lua 与C通过c api传递table
此文转自http://blog.csdn.net/perfect2011/article/details/19200511(感谢...) 首先了解下c++与lua之间的通信: 假设在一个lua文件中有 ...
- Lua C API 遍历 table
http://timothyqiu.com/archives/lua-note-table-traversal-using-c-api/ C API 遍历 Table lua_getglobal(L, ...
- 【翻译】Flink Table Api & SQL —— Table API
本文翻译自官网:Table API https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/tableApi.ht ...
- Nginx+Lua+Redis整合实现高性能API接口 - 网站服务器 - LinuxTone | 运维专家网论坛 - 最棒的Linux运维与开源架构技术交流社区! - Powered by Discuz!
Nginx+Lua+Redis整合实现高性能API接口 - 网站服务器 - LinuxTone | 运维专家网论坛 - 最棒的Linux运维与开源架构技术交流社区! - Powered by Disc ...
- C#进程间通信--API传递参数(SendMessage)
原文 C#进程间通信--API传递参数(SendMessage) 我们不仅可以传递系统已经定义好的消息,还可以传递自定义的消息(只需要发送消息端和接收消息端对自定义的消息值统一即可).下面的发送和接 ...
- c 调用 lua 向lua函数 传递table
参考 https://www.myvoipapp.com/blogs/yxh/2016/07/14/c%E5%90%91lua%E5%87%BD%E6%95%B0%E4%BC%A0%E9%80%92t ...
- 用Nginx+Lua+Redis给百度鹰眼API服务搭建缓存服务中间件(记录过程)
一.环境安装部分 Centos7,Nginx1.14,Redis5.0,luajit-2.1,ngx_devel_kit-0.3.1rc1,lua-nginx-module-0.10.14. 下载安装 ...
- lua中打印所以类型功能实现table嵌套table
lua中打印所以类型功能实现 本人測试 number.string.bool.nil.table嵌套table.userdata没问题 共享一下有什么问题请拍砖 代码例如以下 cclog = func ...
- lua 怎样输出树状结构的table?
为了让游戏前端数据输出更加条理,做了一个简单树状结构来打印数据. ccmlog.lua local function __tostring(value, indent, vmap) local str ...
随机推荐
- Spring MVC集成Spring Data Reids和Spring Session实现Session共享出现:No bean named 'springSessionRepositoryFilter' available
出现这个问题:No bean named 'springSessionRepositoryFilter' available的的原因: 1.Spring MVC加载了多个配置文件导致的,并不是版本问题 ...
- go语言学习之路三:切片
前面讲了变量的有关知识,这里对于其他的数据类型就不多作介绍,(和C差不多),因此重点来讨论下切片. 一.切片是引用类型,这里要稍微介绍两个概念:值类型,构造类型和引用类型 1.值类型:是一种由类型的实 ...
- org.apache.catalina.connector.ClientAbortException: java.io.IOException: APR error:-32
org.apache.catalina.connector.ClientAbortException: java.io.IOException: APR error:-32 Most likely, ...
- iOS中创建自定义的圆角按钮
iOS中很多时候都需要用到指定风格的圆角按钮,尽管UIButton提供了一个方式创建圆角按钮: + (id)buttonWithType:(UIButtonType)buttonType;//指定bu ...
- Mysql 之配置文件my.cnf
mysql配置文件为my.cnf,它所在位置根据安装时设定的. 当mysqld服务启动的时候,默认会按一定的顺序读取配置文件的. 1 2 3 [root@zhu2 ~]# /opt/mysql/lib ...
- UltraEdit UE如何取消保存文件自动备份
高级-配置-文件处理-备份,设置为不备份
- C/C++知识要点2——STL中Vector、Map、Set容器的实现原理
1.Vector是顺序容器.是一个动态数组.支持随机存取.插入.删除.查找等操作,在内存中是一块连续的空间.在原有空间不够情况下自己主动分配空间.添加为原来的两倍.vector随机存取效率高,可是在v ...
- max-points-on-a-line——穷举
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...
- stream_context_create()模拟POST/GET
有时候,我们需要在服务器端模拟 POST/GET 等请求,也就是在 PHP 程序中去实现模拟,该怎么做到呢?或者说,在 PHP 程序里,给你一个数组,如何将这个数组 POST/GET 到另外一个地址呢 ...
- Javascript中没有引用传递,只有按值传递
很多人,包括我,受书本知识消化不彻底的影响,认为 JS 中参数有两种传递方式:数字.字符串等按值传递:数组.对象等按地址(引用)传递.对此种观点,我们要谨慎. var v1 = [] var v2 = ...