第一次写。希望表达能够清楚。

Lua里的table可以实现C++中的数组。Lua的作用一般是用来配置。我把配置的东西写在lua的table里。现在我想要在C++中调用lua中的table,从而把数据传到C++的数组中。

先搞一个一维的table。我是看了《lua程序设计第二版》的25.2节。貌似没有API直接能够取直接取得table的值。或者我不知道吧。书上是用一个getfield函数实现。也就是可能要根据自己的需要重写它。于是模仿的写一个。作用是取得table[key]的值


  1. int getfield(lua_State *L,int key) 
  2.     int result = 0; 
  3.     lua_pushnumber(L,key); 
  4.     lua_gettable(L,-2); 
  5.     if (!lua_isnumber(L,-1)) 
  6.         cout<<"error"<<endl; 
  7.     result = (int)lua_tonumber(L,-1); 
  8.     lua_pop(L,1); 
  9.     return result; 

虽然代码最终运行成功。但是过程中,各种bug 

在书上找到一个函数


  1. static void stackDump(lua_State *L); 

作用是打印交换栈里的数据。

有了这个函数之后,我们对交换栈里的数据情况,就看得一清二楚了。 

//完整代码

 

  1. #include <iostream> 
  2. #include <stdio.h> 
  3. using namespace std; 
  4.  
  5. extern "C" 
  6. #include "lua.h" 
  7. #include "lualib.h" 
  8. #include "lauxlib.h" 
  9. }; 
  10.  
  11. lua_State *L; 
  12. static void stackDump(lua_State *L) 
  13.     int top = lua_gettop(L); 
  14.     for (int i = 1; i <= top; i++) 
  15.     { 
  16.         int t = lua_type(L,i); 
  17.         switch(t) 
  18.         { 
  19.         case LUA_TSTRING: 
  20.             printf("'%s'",lua_tostring(L,i)); 
  21.             break
  22.         case LUA_TBOOLEAN: 
  23.             printf(lua_toboolean(L,i)?"true":"false"); 
  24.             break
  25.         case LUA_TNUMBER: 
  26.             printf("%g",lua_tonumber(L,i)); 
  27.             break
  28.         default
  29.             printf("%s",lua_typename(L,t)); 
  30.         } 
  31.         printf(" "); 
  32.     } 
  33.     printf("\n"); 
  34.  
  35. int getfield(lua_State *L,int key) 
  36.     int result = 0; 
  37.     lua_pushnumber(L,key); 
  38.     cout<<"pushnmber : "
  39.     stackDump(L); 
  40.     cout<<"gettable : "
  41.     lua_gettable(L,-2); 
  42.     stackDump(L); 
  43.     if (!lua_isnumber(L,-1)) 
  44.         cout<<"error"<<endl; 
  45.     result = (int)lua_tonumber(L,-1); 
  46.     cout<<"lua_tonumber : "
  47.     stackDump(L); 
  48.     lua_pop(L,1); 
  49.     cout<<"lua_pop : "
  50.     stackDump(L); 
  51.     return result; 
  52. int main() 
  53.     L = lua_open();
  54.      
  55.     luaL_openlibs(L); 
  56.     luaL_dofile(L,"test.lua"); 
  57.  
  58.     cout<<"start : "
  59.     stackDump(L); 
  60.  
  61.     lua_getglobal(L,"a"); 
  62.     cout<<"getglobal : "
  63.     stackDump(L); 
  64.  
  65.     for (int i = 1; i <= 3; i++) 
  66.     { 
  67.         cout<<"result:"<<getfield(L,i)<<endl; 
  68.     } 
  69.     cout<<endl; 
  70.     system("pause"); 
  71.     lua_close(L); 
  72.     return 0; 

//test.lua

a = {11,12,13} 

截图看下结果。

最右是栈顶。数据变化很清楚。

Getfield函数式假设table已经在栈顶。所以我们在前面必须先用lua_getglobal把table放到栈顶。Pushnumber会把数据压栈。接着gettable会取栈顶的数据,根据给出的table位置,这里是-2,计算出table[栈顶]的数据,把它压栈。Pop则是从栈里退出数据,恢复到一开始的状态。

接着搞一个二维的table。这也是我需要配置的目的所在。

//test.lua

t ={ {11,12,13},{21,22,23} ,}

最后的逗号,好像可有可无。Lua脚本语法比C++宽松多了。

首先我们要修改getfield。作用是取得table[key1][key2]的值 


  1. int getfield(lua_State *L,int key1,int key2) 
  2.     int result = 0; 
  3.     lua_pushnumber(L,key1); 
  4.     lua_gettable(L,-2); 
  5.     lua_pushnumber(L,key2); 
  6.     lua_gettable(L,-2); 
  7.     if (!lua_isnumber(L,-1)) 
  8.         cout<<"error"<<endl; 
  9.     result = (int)lua_tonumber(L,-1); 
  10.     lua_pop(L,2);       //退两个元素 
  11.     return result; 

关键点是在pop时,退了两个元素。 

//完整代码


  1. #include <iostream> 
  2. #include <stdio.h> 
  3. using namespace std; 
  4.  
  5. extern "C" 
  6. #include "lua.h" 
  7. #include "lualib.h" 
  8. #include "lauxlib.h" 
  9. }; 
  10.  
  11. lua_State *L; 
  12. static void stackDump(lua_State *L) 
  13.     int top = lua_gettop(L); 
  14.     for (int i = 1; i <= top; i++) 
  15.     { 
  16.         int t = lua_type(L,i); 
  17.         switch(t) 
  18.         { 
  19.         case LUA_TSTRING: 
  20.             printf("'%s'",lua_tostring(L,i)); 
  21.             break
  22.         case LUA_TBOOLEAN: 
  23.             printf(lua_toboolean(L,i)?"true":"false"); 
  24.             break
  25.         case LUA_TNUMBER: 
  26.             printf("%g",lua_tonumber(L,i)); 
  27.             break
  28.         default
  29.             printf("%s",lua_typename(L,t)); 
  30.         } 
  31.         printf(" "); 
  32.     } 
  33.     printf("\n"); 
  34.  
  35. int getfield(lua_State *L,int key1,int key2) 
  36.     int result = 0; 
  37.     lua_pushnumber(L,key1); 
  38.     cout<<"pushnumber : "
  39.     stackDump(L); 
  40.     lua_gettable(L,-2); 
  41.     cout<<"gettable : "
  42.     stackDump(L); 
  43.     lua_pushnumber(L,key2); 
  44.     cout<<"pushnumber : "
  45.     stackDump(L); 
  46.     lua_gettable(L,-2); 
  47.     cout<<"gettable : "
  48.     stackDump(L); 
  49.     if (!lua_isnumber(L,-1)) 
  50.         cout<<"error"<<endl; 
  51.     result = (int)lua_tonumber(L,-1); 
  52.     cout<<"tonumber : "
  53.     stackDump(L); 
  54.     lua_pop(L,2); 
  55.     cout<<"lua_pop : "
  56.     stackDump(L); 
  57.     return result; 
  58. int main() 
  59.     L = lua_open(); 
  60.      
  61.     luaL_openlibs(L); 
  62.     luaL_dofile(L,"test.lua"); 
  63.  
  64.     cout<<"start : "
  65.     stackDump(L); 
  66.  
  67.     lua_getglobal(L,"t"); 
  68.     cout<<"getglobal : "
  69.     stackDump(L); 
  70.  
  71.     for (int i = 1; i <= 2; i++) 
  72.         for (int j = 1; j <= 3; j++) 
  73.     { 
  74.         cout<<"result:"<<getfield(L,i,j)<<endl; 
  75.     } 
  76.     cout<<endl; 
  77.     system("pause"); 
  78.     lua_close(L); 
  79.     return 0; 
 

结果部分截图

这样C++就调用了lua里二维table的数据。

这里table里是number型,如果是其他类型,需要自己重写getfield函数。