加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

lua和c的交互

发布时间:2020-12-14 22:10:01 所属栏目:大数据 来源:网络整理
导读:extern ? "C" ?{ #include?"lua.h" #include?"lualib.h" #include?"lauxlib.h" } ? #include?iostream #include?string using ? namespace ?std; ???? int ?main() { ???? //Lua示例代码 ???? char ?*szLua_code?= ???????? "r?=?string.gsub(c_Str,?c_Mode,
  1. extern?"C"?{
  2. #include?"lua.h"
  3. #include?"lualib.h"
  4. #include?"lauxlib.h"
  5. }
  6. ?
  7. #include?<iostream>
  8. #include?<string>
  9. using?namespace?std;
  10. ????
  11. int?main()
  12. {
  13. ????//Lua示例代码
  14. ????char?*szLua_code?=
  15. ????????"r?=?string.gsub(c_Str,?c_Mode,?c_Tag)?--宿主给的变量 "
  16. ????????"u?=?string.upper(r)";
  17. //Lua的字符串模式
  18. char?*szMode?=?"(%w+)%s*=%s*(%w+)";
  19. //要处理的字符串
  20. char?*szStr?=?"key1?=?value1?key2?=?value2";
  21. //目标字符串模式
  22. char?*szTag?=?"<%1>%2</%1>";
  23. ?
  24. ????lua_State?*L?=?luaL_newstate();
  25. ????luaL_openlibs(L);
  26. //把一个数据送给Lua
  27. ????lua_pushstring(L,?szMode);
  28. ????lua_setglobal(L,?"c_Mode");
  29. "c_Tag");
  30. "c_Str");
  31. //执行
  32. bool?err?=?luaL_loadbuffer(L,?szLua_code,?strlen(szLua_code),
  33. ????????????????"demo")?||?lua_pcall(L,?0,?0);
  34. ????if(err)
  35. ????{
  36. ????????//如果错误,显示
  37. ????????cerr?<<?lua_tostring(L,?-1);
  38. //弹出栈顶的这个错误信息
  39. ????????lua_pop(L,?1);
  40. ????}
  41. ????else
  42. ????{
  43. ????????//Lua执行后取得全局变量的值
  44. ????????lua_getglobal(L,?"r");
  45. ????????cout?<<?"r?=?"?<<?lua_tostring(L,-1)?<<?endl;
  46. ????????lua_pop(L,?1);
  47. ????????
  48. "u");
  49. ????????cout?<<?"u?=?"?<<?lua_tostring(L,-1)?<<?endl;????
  50. ????}
  51. ????lua_close(L);
  52. return?0;
  53. }


??? 这段代码把字符串中的key=value字符串全部转换成XML格式<key>value</key>
??? 在这个例子中,C++程序通过调用lua_pushstring把C字符串压入栈顶,lua_setglobal的作用是把栈顶的数据传到Lua环境中作为全局变量。
??? 执行代码完成后,使用lua_getglobal从Lua环境中取得全局变量压入栈顶,然后使用lua_tostring把栈顶的数据转成字符串。由于lua_tostring本身没有出栈功能,所以为了平衡(即调用前与调用后栈里的数据量不变),使用lua_pop弹出由lua_setglobal压入的数据。
??? 从上面的例子可以看出,C++和Lua之间一直围绕着栈在转,可见栈是极为重要的。有必要列出一些Lua C API中的主要栈操作先,它们的作用直接可以从函数名中看出。
压入元素到栈里

void lua_pushnil (lua_State *L);    
void lua_pushboolean (lua_State *L,int bool);
void lua_pushnumber (lua_State *L,double n);
void lua_pushlstring (lua_State *L,const char *s,size_t length);
void lua_pushstring (lua_State *L,const char *s);
void lua_pushcfunction (lua_State *L,lua_CFunction fn);


查询栈里的元素

lua_isnil (lua_State *L,int index);
lua_isboolean (lua_State *L,int index);
int lua_isnumber (lua_State *L,int index);
int lua_isstring (lua_State *L,int index);
int lua_isfunction (lua_State *L,int index);
int lua_istable (lua_State *L,int index);
int lua_isuserdata (lua_State *L,int index);
lua_islightuserdata (lua_State *L,int index);
lua_isthread (lua_State *L,int index);

?

转换栈里的元素

int                lua_toboolean (lua_State *L,int index);
double            lua_tonumber (lua_State *L,int index);
const char *    lua_tostring (lua_State *L,int index);
const char *    lua_tolstring (lua_State *L,int idx,size_t *len);
size_t            lua_strlen (lua_State *L,int index);
lua_CFunction   lua_tocfunction (lua_State *L,int idx);
void *          lua_touserdata (lua_State *L,int idx);
lua_State *     lua_tothread (lua_State *L,int idx);

?

Lua栈的维护

int  lua_gettop (lua_State *L);
    取得栈顶元素的索引,即栈中元素的个数
void lua_settop (lua_State *L,int index);
    设置栈顶索引,即设置栈中元素的个数,如果index<0,则从栈顶往下数,下同
void lua_pushvalue (lua_State *L,int index);
    把栈中指定索引的元素复制一份到栈顶
void lua_remove (lua_State *L,int index);
    删除指定索引的元素
void lua_insert (lua_State *L,int index);
    移动栈顶元素到指定索引的位置,栈中数目没有改变
void lua_replace (lua_State *L,int index);
    从栈顶弹出元素值并将其设置到指定索引位置,栈中的数目减一
int  lua_checkstack (lua_State *L,int extra);
    确保堆栈上至少有 extra 个空位。如果不能把堆栈扩展到相应的尺寸,函数返回 false 。这个函数永远不会缩小堆栈。
int  lua_pop(L,n)
    从栈顶弹出n个元素,它是一个lua_settop的包装:#define lua_pop(L,n)  lua_settop(L,-(n)-1)

?

表的操作
上面的列表中并没有lua_pushtable和lua_totable,那么怎样取得或设置Lua中的table数据呢?
在Lua中,table是一个很重要的数据类型,在table中不仅可以象C中的数据一样放一组数据,还可以象map一样以key=value的方式存放数据,如Lua代码中的:

tb = {"abc",12,true,x=10,y=20,z=30}

??? 前三个数据可以用tb[1]~tb[3]取得
??? 而后三个数据通过tb.x,tb.y,tb.z取得
尽管看起来很牛叉,不过剥开神奇的外衣,实际上Lua的table中,所有的数据都是以key=value的形式存放的,这句Lua代码也可以写成:

tb = {[1]="

??? 它的形式就是[key]=value,所谓的tb.x只是tb["x"]的语法糖而已,如果愿意,也可以用tb["x"]取得这个数据10。
我们把上面的例子改成使用表的

    ...
  1. int?main()
  2. {
  3. ????//Lua示例代码,使用table
  4. ????char?*szLua_code?=
  5. ????????"x?=?{}?--用于存放结果的table "
  6. ????????"x[1],x[2]?=?string.gsub(c.Str,?c.Mode,?c.Tag)?--x[1]里是结果,x[2]里是替换次数 "
  7. ????????"x.u?=?string.upper(x[1])";
  8. ????//Lua的字符串模式
  9. ????char?*szMode?=?"(%w+)%s*=%s*(%w+)";
  10. //要处理的字符串
  11. char?*szStr?=?"key1?=?value1?key2?=?value2";
  12. //目标字符串模式
  13. char?*szTag?=?"<%1>%2</%1>";
  14. ?
  15. ????lua_State?*L?=?luaL_newstate();
  16. ????luaL_openlibs(L);
  17. ?
  18. //把一个tabele送给Lua
  19. ????lua_newtable(L);????//新建一个table并压入栈顶
  20. ????lua_pushstring(L,?"Mode");//?key
  21. ????lua_pushstring(L,?szMode);//?value
  22. //设置newtable[Mode]=szMode
  23. //由于上面两次压栈,现在table元素排在栈顶往下数第三的位置
  24. ????lua_settable(L,?-3);
  25. //lua_settable会自己弹出上面压入的key和value
  26. "Tag");//?key
  27. //?value
  28. ????lua_settable(L,?-3);????//设置newtable[Tag]=szTag
  29. "Str");//设置newtable[Str]=szStr
  30. ????lua_setglobal(L,"c");?//将栈顶元素(newtable)置为Lua中的全局变量c
  31. //执行
  32. ????????????????"demo")?||?lua_pcall(L,?0);
  33. ????if(err)
  34. ????{
  35. ????????//如果错误,显示
  36. ????????cerr?<<?lua_tostring(L,?-1);
  37. //弹出栈顶的这个错误信息
  38. ????????lua_pop(L,?1);
  39. ????}
  40. ????else
  41. ????{
  42. ????????//Lua执行后取得全局变量的值
  43. ????????lua_getglobal(L,?"x");
  44. //这个x应该是个table
  45. ????????if(lua_istable(L,-1))
  46. ????????{
  47. ????????????//取得x.u,即x["u"]
  48. ????????????lua_pushstring(L,"u");????//key
  49. //由于这次压栈,x处于栈顶第二位置
  50. ????????????lua_gettable(L,-2);
  51. //lua_gettable会弹出上面压入的key,然后把对应的value压入
  52. ????????????//取得数据,然后从栈中弹出这个value
  53. ????????????cout?<<?"x.u?=?"?<<?lua_tostring(L,-1)?<<?endl;
  54. ????????????lua_pop(L,?1);
  55. ????????????
  56. //取得x[1]和x[2]
  57. ????????????for(int?i=1;?i<=2;?i++)
  58. ????????????{
  59. ????????????????//除了key是数字外,与上面的没什么区别
  60. ????????????????lua_pushnumber(L,i);
  61. ????????????????lua_gettable(L,-2);
  62. ????????????????cout?<<?"x["?<<?i?<<"]?=?"?<<?lua_tostring(L,-1)?<<?endl;
  63. ????????????????lua_pop(L,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ????????????}
  64. ????????}
  65. //弹出栈顶的x
  66. ????????lua_pop(L,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ????}
  67. ????lua_close(L);
  68. return?0;
  69. }

本例中用到的新Lua C API是:

void lua_newtable (lua_State *L);
    新建一个空的table并压入栈顶。
void lua_settable (lua_State *L,int idx);
    lua_settable以table在栈中的索引作为参数,并将栈顶的key和value出栈,用这两个值修改table。
void lua_gettable (lua_State *L,int idx);
    lua_gettable以table在栈中的索引作为参数,弹出栈顶的元素作为key,返回与key对应的value并压入栈顶。
最后,Lua告别针对table提供了存取函数
void lua_rawgeti (lua_State *L,int n)
    取得table[n]并放到栈顶,上例中69-70行的lua_pushnumber(L,i);lua_gettable(L,-2);可以用lua_rawgeti(L,-1)代替。
lua_getfield (lua_State *L,const char *k)
    取得table.k并放到栈顶,上例中57-59行的lua_pushstring(L,"u");lua_gettable(L,-2);可以替换成lua_getfield(L,-1,"u")。
void lua_setfield (lua_State *L,const char *k)
    把栈顶的数据作为value放入table.k中,上例中的形如lua_pushstring(L,"key");lua_pushstring(L,value);lua_settable(L,-3);可以改成lua_pushstring(L,value);lua_setfield(L,-2,"key");的形式。
void lua_rawseti (lua_State *L,int n)
    把栈顶的数据作为value放入table[n]中
 
http://blog.csdn.net/zhangjingyangguang/article/details/5221691

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读