本文转自http://blog.csdn.net/a_asinceo/article/details/49907903(感谢。。。)

一、单个参数的传递

首先我们在Lua中注册一个C类PJYCallbackMgr,其中一个方法为:

  1. int testLuaCall(lua_State* L){
  2. ...
  3. ...
  1. 然后我们在Lua调用这个方法,传入各种值,首先我们传入一个int,例如:
  1. <pre name="code" class="java">PJYCallbackMgr.testlua(1007)

那么在C层我们怎么获取这个1007的值呢?

在这之前我们先来看看,Lua调用这个方法之后,就会1007这个值压入到堆栈lua_State中,

因为只有一个值,所以此时lua_State的堆栈状态应该是这样的:

//        说明             栈内容             排序             排序
//   栈顶/栈底           1007                 -1                  1

因为只有一个值,所有这个1007,既是栈底也是栈顶,注意两个不同方法的排序方式。排序方式不明白,请参考上面的文章。

因此我们在C层要做的事情就是通过这个 lua_State* L来获取栈中的值。

代码:

  1. //首先检查一下是否一个number
  2. luaL_checktype(L, 1, LUA_TNUMBER);
  3. int luavalue= lua_tonumber(L,-1);
  4. CCLOG("luavalue = %d", luavalue);

你会看到输出:

  二、多个参数的传递

在Lua中我们传入多个参数给C类,如下:

  1. <span style="font-size:14px;">   PJYCallbackMgr.testlua(1007,"numberA","numberB")</span>

那么我们在C类中如何获取?

  1. ------------------------此时栈中的内容应该如下-------------------
  2. 说明         栈内容          排序             排序
  3. 栈顶是       numberB          -1               3
  4. numberA          -2               2
  5. 栈低是         1007           -3               1
  6. 首先检查一下是否一个number   如果此时还是先检查序号1的index栈内容 不会报错 以
  7. luaL_checktype(L, 1, LUA_TNUMBER);
  8. //根据以上的栈 我们轻易地获取其值
  9. if (lua_isstring(L, -1)){
  10. std::string numberBstring = lua_tostring(L, -1);
  11. const char* numberB = numberBstring.c_str();
  12. CCLOG("numberB = %s", numberB);
  13. }
  14. if (lua_isstring(L, -2)){
  15. std::string numberAstring = lua_tostring(L, -2);
  16. const char* numberA = numberAstring.c_str();
  17. CCLOG("numberA = %s", numberA);
  18. }
  19. if (lua_isnumber(L, -3)){
  20. int  luanumber = lua_tonumber(L, -3);
  21. CCLOG("luanumber = %d", luanumber);
  22. }

你会看到输出:

2.table的传递和标记

table是Lua中最重要的一环,很多Lua中的方法原原理 , 结构原理都会用到table。

为了更好的了解table的传递,需要先阅读以下的参考文章。

如何在Lua与C/C++之间实现table数据的交换

 一、简单table  

那么我们就在Lua中传递一个table到C中:

  1. local tableA = {1007,"numberA","numberB"}
  2. PJYCallbackMgr.testlua(tableA)

在C中:注意看注释

  1. //------------------------此时栈中的内容应该如下-------------------
  2. //    说明         栈内容          排序             排序
  3. //  栈低/栈顶      table           -1               1
  4. luaL_checktype(L, 1, LUA_TTABLE);//检查栈顶是否一个table
  5. lua_pushnumber(L, 1);//先向栈中压入一个数字  为何要压入一个数字呢?
  6. //------------------------此时栈中的内容应该如下-------------------
  7. //    说明         栈内容          排序             排序
  8. //    int            1             -1                2
  9. //    栈低         table           -2                1
  10. lua_gettable(L, -2);//获取table中的第一个元素value 并把这个value放到栈顶
  11. //------------------------此时栈中的内容应该如下-------------------
  12. //    说明         栈内容          排序             排序
  13. //    int          1007             -1                2
  14. //    栈低         table            -2                1
  15. if (lua_isnumber(L, 2)){  //再获取栈顶的1007 value
  16. int  luanumber = lua_tonumber(L, 2);
  17. CCLOG("luanumber = %d", luanumber);
  18. }
  19. //然后出栈  这一步很重要,同样地我们也应该在上面多参数传递时,获取完栈顶数值之后,出栈,
  20. //让C语言保持多栈顶的控制,而不改变整个栈
  21. //把栈顶的数值弹出
  22. lua_pop(L, 1);
  23. //------------------------此时栈中的内容应该如下-------------------
  24. //    说明         栈内容          排序             排序
  25. //    栈低         table            -1                1
  26. //得到这个原始干净的栈之后 就会继续获取下面的值
  27. lua_pushnumber(L, 2);
  28. lua_gettable(L, -2);
  29. if (lua_isstring(L, -1)){
  30. std::string luastring = lua_tostring(L, -1);
  31. const char* numberA = luastring.c_str();
  32. CCLOG("numberA = %s", numberA);
  33. }
  34. lua_pop(L, 1);
  35. //同理可以得到
  36. lua_pushnumber(L, 3);
  37. lua_gettable(L, -2);
  38. if (lua_isstring(L, -1)){
  39. std::string luastring = lua_tostring(L, -1);
  40. const char* numberB = luastring.c_str();
  41. CCLOG("numberA = %s", numberB);
  42. }
  43. 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]就是第一个元素的值。

  1. local tableA = {1007,"numberA","numberB"}
  2. PJYCallbackMgr.testlua(tableA)
  3. print(tableA[1]);

因此,我们在获取table元素值的时候,需要先push一个栈顶值进去作为table里面的key,在获取key对应的value。

二、复杂的table

我们再往C中传递一个复杂的table看看,再C中如何获取。

  1. local payinfo={roleid="" ,money=0,productName="",callBackStr="",
  2. gameGold="",rate=0}
  3. PJYCallbackMgr.testlua(payinfo)

     参考上面的文章,和结合上文,我们很容易就可以获取roleid等各个key对应的值,先push一个key对应的string,进去栈中,然后同个gettable获取对应的值

但这个方法往往要对栈进行push和pop,稍不注意就出错。所以我们可以利用C api中另一个方法更直观地获取这种table中的值。

  1. luaL_checktype(L, 1, LUA_TTABLE);//检查栈顶是否一个table
  2. lua_getfield(L,-1,"roleid");//如果是table 取出它的roleid值放到栈顶 此时的栈
  3. //    说明         栈内容          排序             排序
  4. //   栈顶是       roleid_value      -1               2
  5. //   栈低是         table           -2               1
  6. if (lua_isstring(L,-1)){
  7. std::string luastring = lua_tostring(L, -1);
  8. const char* lualog = luastring.c_str();
  9. CCLOG("roleid = %s", lualog);
  10. }
  11. //此时roleid_value已经在栈顶 并没有出栈
  12. //获取money
  13. lua_getfield(L, 1, "money");
  14. if (lua_isnumber(L,-1)){
  15. int  money = lua_tonumber(L, -1);
  16. CCLOG("money = %d", money);
  17. }
  18. //此时money_value已经在栈顶 并没有出栈  所以要用序号1来index栈低的table
  19. lua_getfield(L, 1, "productName");
  20. if (lua_isnumber(L, -1)){
  21. std::string productNamestring = lua_tostring(L, -1);
  22. const char* productName = productNamestring.c_str();
  23. CCLOG("productName = %s", productName);
  24. }
  25. //此时productName_value已经在栈顶 并没有出栈  所以要用序号1来index栈低的table
  26. //透传字段
  27. lua_getfield(L, 1, "callBackStr");
  28. if (lua_isnumber(L, -1)){
  29. std::string callBackStrstring = lua_tostring(L, -1);
  30. const char* callBackStr = callBackStrstring.c_str();
  31. CCLOG("callBackStr = %s", callBackStr);
  32. }
  33. //主要交易货币名称
  34. lua_getfield(L, 1, "gameGold");
  35. if (lua_isnumber(L, -1)){
  36. std::string gameGoldstring = lua_tostring(L, -1);
  37. const char* gameGold = gameGoldstring.c_str();
  38. CCLOG("gameGold = %s", gameGold);
  39. }
  40. //获取money
  41. lua_getfield(L, 1, "rate");
  42. if (lua_isnumber(L, -1)){
  43. int  rate = lua_tonumber(L, -1);
  44. CCLOG("rate = %d", rate);
  45. }

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)的更多相关文章

  1. lua 与C通过c api传递table

    此文转自http://blog.csdn.net/perfect2011/article/details/19200511(感谢...) 首先了解下c++与lua之间的通信: 假设在一个lua文件中有 ...

  2. Lua C API 遍历 table

    http://timothyqiu.com/archives/lua-note-table-traversal-using-c-api/ C API 遍历 Table lua_getglobal(L, ...

  3. 【翻译】Flink Table Api & SQL —— Table API

    本文翻译自官网:Table API  https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/tableApi.ht ...

  4. Nginx+Lua+Redis整合实现高性能API接口 - 网站服务器 - LinuxTone | 运维专家网论坛 - 最棒的Linux运维与开源架构技术交流社区! - Powered by Discuz!

    Nginx+Lua+Redis整合实现高性能API接口 - 网站服务器 - LinuxTone | 运维专家网论坛 - 最棒的Linux运维与开源架构技术交流社区! - Powered by Disc ...

  5. C#进程间通信--API传递参数(SendMessage)

    原文 C#进程间通信--API传递参数(SendMessage)  我们不仅可以传递系统已经定义好的消息,还可以传递自定义的消息(只需要发送消息端和接收消息端对自定义的消息值统一即可).下面的发送和接 ...

  6. 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 ...

  7. 用Nginx+Lua+Redis给百度鹰眼API服务搭建缓存服务中间件(记录过程)

    一.环境安装部分 Centos7,Nginx1.14,Redis5.0,luajit-2.1,ngx_devel_kit-0.3.1rc1,lua-nginx-module-0.10.14. 下载安装 ...

  8. lua中打印所以类型功能实现table嵌套table

    lua中打印所以类型功能实现 本人測试 number.string.bool.nil.table嵌套table.userdata没问题 共享一下有什么问题请拍砖 代码例如以下 cclog = func ...

  9. lua 怎样输出树状结构的table?

    为了让游戏前端数据输出更加条理,做了一个简单树状结构来打印数据. ccmlog.lua local function __tostring(value, indent, vmap) local str ...

随机推荐

  1. Liunx 下Redis 的安装

    一.Redis 的简介 Redis是一款开源的.高性能的键-值存储.它常被称作是一款数据结构服务器,它是一个key-value存储系统.和Memcache类似,Memecache只支持字符窜的数据类型 ...

  2. Dfs学习经验(纸上运行理解DFS)【两道题】

    首先我想吐槽的是,在CSDN上搞了好久还是不能发博客,就是点下发表丝毫反应都没有的,我稍微百度了几次还是没有找到解决方法,在CSDN的BBS上也求助过管理员但是没有收到答复真是烦躁,导致我新生入学以来 ...

  3. Nginx阻止DDoS攻击的教程收集(转)(待实践)

    DDoS估计是一个非常头痛的问题. 分布式拒绝服务攻击(DDoS)指的是通过多台机器向一个服务或者网站发送大量看似合法的数据包使其网络阻塞.资源耗尽从而不能为正常用户提供正常服务的攻击手段.随着互联网 ...

  4. cut printf awk sed grep笔记

    名称 作用 参数 实例 cut 截取某列,可指定分隔 -f 列号 -d 分隔符 cut -d ":" -f 1, 3 /etc/passwd 截取第一列和第三列 printf pr ...

  5. 全能无线渗透测试工具,一个LAZY就搞定了

    近来一直在研究无线安全方面的东西,特别是在无线渗透测试这块,每次渗透测试时总要来回不停的切换操作和挑选利器,很是麻烦.就想看看是否可以有一款功能全面的集合型工具. 正所谓功夫不负有心人,还真有这么一个 ...

  6. Meteor 从一个列表页进入详情页怎样高速显示详情

    无论是做android开发,还是做网页web开发,都 会有列表,都须要点击列表进入列表项的详情页面,查看具体信息,能常情况下,我们都是将这一列表项的id传到详情页,由详情页再到数据库查询具体信息. 在 ...

  7. js 验证 输入值 全是数字

    1.使用isNaN()函数 isNaN()的缺点就在于 null.空格以及空串会被按照0来处理 NaN: Not a Number /** *判断是否是数字 **/ function isRealNu ...

  8. winform中使用ReportViewer的时候,找不到报表数据面板.

    最近在做winform的报表项目,看人家教程里都有报表数据面板,可我的怎么都找不到,我的是VS2012,最后终于找到,首先必须在报表设计TAB上(选中它),然后选择视图->报表数据

  9. Java学习之集合

    1.ArrayList:采用数组的形式保存对象,这种方式将对象保存在连续的位置中,所以查询效率比较高,但是插入删除时麻烦,并且ArrayList不是线程安全的. 2.Vector:保存对象的方式与Ar ...

  10. cocoaPods 安装和应用

    一.安装 下载安装CocoaPods需要Ruby环境 1. 检测gem版本 $ gem -v 如果gem版本小于2.6.x,则需要更新gem 2. 更新gem(gem版本高于2.6.x可跳过此步) 检 ...