• lua 与C通过c api传递table (2)


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

    一、单个参数的传递

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

             

    1. int testLuaCall(lua_State* L){  
    2.        ...  
    3.        ...  

     

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


            你会看到输出:

            



    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.   
    4. //  栈低/栈顶      table           -1               1  
    5.   
    6.   
    7. luaL_checktype(L, 1, LUA_TTABLE);//检查栈顶是否一个table  
    8.   
    9. lua_pushnumber(L, 1);//先向栈中压入一个数字  为何要压入一个数字呢?  
    10.   
    11. //------------------------此时栈中的内容应该如下-------------------  
    12. //    说明         栈内容          排序             排序  
    13. //    int            1             -1                2  
    14. //    栈低         table           -2                1  
    15.   
    16. lua_gettable(L, -2);//获取table中的第一个元素value 并把这个value放到栈顶  
    17.   
    18. //------------------------此时栈中的内容应该如下-------------------  
    19. //    说明         栈内容          排序             排序  
    20. //    int          1007             -1                2  
    21. //    栈低         table            -2                1  
    22.   
    23.   
    24. if (lua_isnumber(L, 2)){  //再获取栈顶的1007 value  
    25.   
    26.     int  luanumber = lua_tonumber(L, 2);  
    27.   
    28.     CCLOG("luanumber = %d", luanumber);  
    29. }  
    30. //然后出栈  这一步很重要,同样地我们也应该在上面多参数传递时,获取完栈顶数值之后,出栈,  
    31. //让C语言保持多栈顶的控制,而不改变整个栈  
    32. //把栈顶的数值弹出  
    33. lua_pop(L, 1);  
    34.   
    35. //------------------------此时栈中的内容应该如下-------------------  
    36. //    说明         栈内容          排序             排序  
    37.   
    38. //    栈低         table            -1                1  
    39.   
    40.    //得到这个原始干净的栈之后 就会继续获取下面的值  
    41. lua_pushnumber(L, 2);  
    42. lua_gettable(L, -2);  
    43. if (lua_isstring(L, -1)){  
    44.     std::string luastring = lua_tostring(L, -1);  
    45.     const char* numberA = luastring.c_str();  
    46.     CCLOG("numberA = %s", numberA);  
    47. }  
    48. lua_pop(L, 1);  
    49.   
    50. //同理可以得到  
    51. lua_pushnumber(L, 3);  
    52. lua_gettable(L, -2);  
    53. if (lua_isstring(L, -1)){  
    54.     std::string luastring = lua_tostring(L, -1);  
    55.     const char* numberB = luastring.c_str();  
    56.     CCLOG("numberA = %s", numberB);  
    57. }  
    58. 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.   
    3.     lua_getfield(L,-1,"roleid");//如果是table 取出它的roleid值放到栈顶 此时的栈  
    4.   
    5.     //    说明         栈内容          排序             排序  
    6.     //   栈顶是       roleid_value      -1               2  
    7.     //   栈低是         table           -2               1  
    8.   
    9.     if (lua_isstring(L,-1)){  
    10.         std::string luastring = lua_tostring(L, -1);  
    11.         const char* lualog = luastring.c_str();  
    12.         CCLOG("roleid = %s", lualog);  
    13.     }  
    14.     //此时roleid_value已经在栈顶 并没有出栈  
    15.     //获取money  
    16.     lua_getfield(L, 1, "money");  
    17.     if (lua_isnumber(L,-1)){  
    18.   
    19.         int  money = lua_tonumber(L, -1);  
    20.           
    21.         CCLOG("money = %d", money);  
    22.     }  
    23.     //此时money_value已经在栈顶 并没有出栈  所以要用序号1来index栈低的table  
    24.   
    25.     lua_getfield(L, 1, "productName");  
    26.     if (lua_isnumber(L, -1)){  
    27.   
    28.         std::string productNamestring = lua_tostring(L, -1);  
    29.         const char* productName = productNamestring.c_str();  
    30.   
    31.         CCLOG("productName = %s", productName);  
    32.     }  
    33.     //此时productName_value已经在栈顶 并没有出栈  所以要用序号1来index栈低的table  
    34.   
    35.   
    36.     //透传字段  
    37.     lua_getfield(L, 1, "callBackStr");  
    38.     if (lua_isnumber(L, -1)){  
    39.   
    40.         std::string callBackStrstring = lua_tostring(L, -1);  
    41.         const char* callBackStr = callBackStrstring.c_str();  
    42.   
    43.         CCLOG("callBackStr = %s", callBackStr);  
    44.     }  
    45.   
    46.   
    47.     //主要交易货币名称  
    48.     lua_getfield(L, 1, "gameGold");  
    49.     if (lua_isnumber(L, -1)){  
    50.   
    51.         std::string gameGoldstring = lua_tostring(L, -1);  
    52.         const char* gameGold = gameGoldstring.c_str();  
    53.   
    54.         CCLOG("gameGold = %s", gameGold);  
    55.     }  
    56.   
    57.   
    58.     //获取money  
    59.     lua_getfield(L, 1, "rate");  
    60.     if (lua_isnumber(L, -1)){  
    61.   
    62.         int  rate = lua_tonumber(L, -1);  
    63.   
    64.         CCLOG("rate = %d", rate);  
    65.     }  


    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
         }
    }


  • 相关阅读:
    约瑟夫问题的解法集锦
    java调用com组件将office文件转换成pdf
    hdu(1069)——Monkey and Banana(LIS变形)
    Unix网络编程之环境搭建
    atitit. java queue 队列体系and自己定义基于数据库的队列总结o7t
    怎样使Dialog像Activity一样随心所欲的使用?
    获取全部分组中某列最大的行
    Class C++
    spring mvc +Mybatis3.1 整合的时候异常
    Linux 编译C++ 与 设置 Vim
  • 原文地址:https://www.cnblogs.com/thinkinglife/p/5235042.html
Copyright © 2020-2023  润新知