lua 和 C 语言进行交互 —— 如何传递table

http://blog.csdn.net/cjfeii/article/details/25593509

方法1:

采用 lua_pushstring/lua_pushnumber 传递key、value,然后通过 lua_settable 设置 table 中的kv对,like this:
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. lua_pushnumber(L, 1);  
  2. lua_pushstring(L, "value1");  
  3. lua_settable(L, -3);  
其中“lua_settable(L, -3)”表示将前压栈中的前两个参数作为一个kv对放到table中。
1. 首先编写 lua 文件 lua_test.lua:
[plain]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. -- file: lua_test.lua  
  2. function domain(i)  
  3.   
  4.     -- call C function.  
  5.     local tab = gettab()   
  6.   
  7.     -- show key and value  
  8.     for k, v in pairs(tab) do  
  9.         print("key: ".. k)  
  10.         print("val: ".. v)  
  11.     print()  
  12.     end  
  13.   
  14. end  
2. 其中 gettab 是 C 中注册的函数,下面是对应的 C 代码 c_test.c :
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  * file: c_test.c 
  3.  */  
  4. #include <lua.h>  
  5. #include <lauxlib.h>  
  6. #include <lualib.h>  
  7. #include <string.h>  
  8. #include <unistd.h>  
  9. #include <stdio.h>  
  10.   
  11. int get_tab(lua_State *L)  
  12. {  
  13.     /* create table. */  
  14.     lua_newtable(L);  
  15.   
  16.     /* push (key, value). */  
  17.     int i;  
  18.     char value[10] = {0};  
  19.     for(i=0; i<5; ++i)  
  20.     {  
  21.         sprintf(value, "value%d", i+1);  
  22.         lua_pushnumber(L, i+1);    //key  
  23.         lua_pushstring(L, value);  //value  
  24.         lua_settable(L, -3);       //push key,value  
  25.     }  
  26.   
  27.     /* deal return. */  
  28.     return 1;  
  29. }  
  30.   
  31. int main()  
  32. {  
  33.     /* create a state and load standard library. */  
  34.     lua_State* L = luaL_newstate();  
  35.   
  36.     /* opens all standard Lua libraries into the given state. */  
  37.     luaL_openlibs(L);  
  38.   
  39.     /* register function be called by lua. */  
  40.     lua_register(L, "gettab", get_tab);  
  41.   
  42.     /* load and exec the specified lua file. */  
  43.     int error = luaL_dofile(L, "lua_test.lua");  
  44.     if(error) {  
  45.         perror("luaL_dofile error");  
  46.         exit(1);  
  47.     }  
  48.   
  49.     /* get the domain function from lua file. */   
  50.     lua_getglobal(L,"domain");  
  51.   
  52.     /* exec the domain function. */  
  53.     error = lua_pcall(L, 0, 0, 0);  
  54.     if (error) {  
  55.         fprintf(stderr,"%s\n",lua_tostring(L,-1));  
  56.         lua_pop(L,1);  
  57.     }  
  58.   
  59.     /* close lua state. */  
  60.     lua_close(L);  
  61.   
  62.     return 0;  
  63. }  
使用一下命令编译:
[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. gcc c_test.c -I/usr/local/include/luajit-2.0 -L/usr/local/lib -lluajit-5.1 -o exe  
note:环境需要装luajit

3. 下面执行编译出来的可执行文件 exe:
[plain]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. key: 1  
  2. val: value1  
  3.   
  4. key: 2  
  5. val: value2  
  6.   
  7. key: 3  
  8. val: value3  
  9.   
  10. key: 4  
  11. val: value4  
  12.   
  13. key: 5  
  14. val: value5  

方法2:

上面对 table 的 kv 对是这样处理的:
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. lua_pushnumber(L, i+1);    //key  
  2. lua_pushstring(L, value);  //value  
  3. lua_settable(L, -3);       //push key,value  
其实有一种效率高的方法,like this:
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. lua_pushstring(L, value);  
  2. lua_rawseti(L, -2, i++);  

最后再写一种 lua 调用函数库的方法:
1. 首先编写 C 文件 so_test.c:
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /*  
  2.  * file:so_test.c 
  3.  */  
  4. #include <lua.h>  
  5. #include <lauxlib.h>  
  6. #include <lualib.h>  
  7. #include <stdio.h>  
  8.   
  9. int get_tab(lua_State *L)  
  10. {  
  11.     /* get the input. */  
  12.     int num = lua_tonumber(L, 1);  
  13.   
  14.     /* create table. */  
  15.     lua_newtable(L);  
  16.   
  17.     /* push (key, value). */  
  18.     int i;  
  19.     char value[10] = {0};  
  20.     for(i=0; i<num; ++i)  
  21.     {  
  22.         sprintf(value, "value%d", i+1);  
  23.         lua_pushnumber(L, i+1);  
  24.         lua_pushstring(L, value);  
  25.         lua_settable(L, -3);  
  26.     }  
  27.   
  28.     /* deal return. */  
  29.     return 1;  
  30. }  
  31.   
  32. static const luaL_Reg mylib[] = {  
  33.     {"get_tab", get_tab},  
  34.     {NULL, NULL}  
  35. };  
  36.   
  37. int luaopen_lua_test(lua_State *L) {  
  38.     luaL_register(L, "lua_test", mylib);  
  39.     return 0;  
  40. }  
用以下命令编译出动态库 lua_test.so:
[sql]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. gcc so_test.c -shared -fPIC -I/usr/local/include/luajit-2.0/ -I/usr/include/ -lluajit-5.1 -o lua_test.so  

2. 然后编写 lua 测试代码 test.lua:
[plain]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. -- file: test.lua  
  2. local test = require('lua_test')  
  3.   
  4. function domain(num)  
  5.   
  6.     -- call C function.  
  7.     local tab = test.get_tab(num)   
  8.   
  9.     -- show key and value  
  10.     for k, v in pairs(tab) do  
  11.         print("key: ".. k)  
  12.         print("val: ".. v)  
  13.     print()  
  14.     end  
  15.   
  16. end  
  17.   
  18. domain(5)  

3. 执行 lua 代码:
[plain]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. # lua test.lua   
  2. key: 1  
  3. val: value1  
  4.   
  5. key: 2  
  6. val: value2  
  7.   
  8. key: 3  
  9. val: value3  
  10.   
  11. key: 4  
  12. val: value4  
  13.   
  14. key: 5  
  15. val: value5  

以上代码的编译执行环境:

os:CentOS release 6.4 (Final)

gcc:gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3)

lua:Lua 5.1.4

luajit:LuaJIT 2.0.2

参考书: Programming in Lua
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
详细描述Lua和C之间相互传递Table类型数据 /* ====================================================== */ // 遍历Lua传入的Table类型参数, 获取它的Key/Value, 其关键操作是 lua_next() // lua_next() 返回1表示读取成功,返回0表示已经没有数据可读了 // lua_next() 会使用栈顶元素作为Key去定位本次需要取出Table里面的那个值对 // 如果Key=nil, 那就表示本次取出的是第一个元素 // 它会先将当前的这个Key弹出,然后将本次取出的Key/Value压入栈, Value在栈顶 // 一个比较隐晦的处理就是, 我们不应直接使用lua_tostring(L, -2)来读取Key // 因为lua_tostring()在Key类型不是字符串时, 它会修改栈上的Key数据 // 这样, 下次调用lua_next()时, 就会因为Key被修改了而导致错误 // 为此,先调用lua_pushvalue(L, -2),将它Copy一份到栈顶,对这个Copy进行lua_tostring() // 读取Key,Value到C变量里面后,将Value和Copy弹出,留着Key在栈顶,给下次lua_next()用 // // 指令及栈图变化如下: (假如Table的栈下标是Index) // 0. 刚进入函数时 ...Table, ... <--- 这里栈顶 // 1. lua_pushnil(L) ...Table, ..., nil <--- 这里栈顶 // 2. lua_next(L, Index) ...Table, ..., Key, Value <--- 这里栈顶 // 3. lua_pushvalue(L, -2) ...Table, ..., Key, Value, KeyCopy <--- 这里栈顶 // 4. lua_pop(L, 2), ...Table, ..., Key <--- 这里栈顶 // ... 如此重复2,3,4 // N. lua_next(L, Index)返回0 ...Table, ... <--- 这里栈顶 /* ====================================================== */

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值