Chinaunix首页 | 论坛 | 博客
  • 博客访问: 56568
  • 博文数量: 13
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-26 15:04
文章分类

全部博文(13)

文章存档

2015年(13)

我的朋友

分类: Android平台

2015-05-24 22:35:19

  今天看了一篇分析lua++的文章,它提到在lua里访问c struct的成员的一个方法是,在c里给每个成员写一个函数,像name,就写成return tbl.name这样的,把这些getter放到metatable的一张表里(取名叫get),用"name"作为key。把metatable的__index属性指向一个函数,这个函数相当于一个中转站,根据缺失的key,调用get表里对应key的getter。
  是很很巧妙的方法。之所以巧妙,是因为上面的操作,几乎所有的代码,都可以用程序来生成。只需要扫描和分析头文件。
  lua++大概就是这么做的吧。
  尝试了一晚上,差不多做成了一个demo,只是getter没有在c里写,直接在lua里写的。这样肯定是不妥的,但为了加快速度,只好...
  下面是主要的代码:

点击(此处)折叠或打开

  1. wrapper.c
  2. #include<stdio.h>
  3. #include<lua.h>
  4. #include<lualib.h>
  5. #include<dog.h>



  6. /*lua 似乎是这样,每次调用一个fucntion时,会清除栈上的参数和function*/
  7. int getAttr(lua_State *L){
  8.     char *key = lua_tostring(L, -1);

  9.     lua_getmetatable(L, -2);
  10.     lua_pushstring(L, "get");
  11.     lua_gettable(L, -2);    /**stack top:table= mtbl.get*/
  12.     lua_pushstring(L, key);
  13.     lua_gettable(L, -2);    /**stack top:function = get.key*/
  14.     int err = lua_pcall(L, 0, 1, 0);    /**核心在这里... ,暂时简化,规定get表的一堆getter都只返回1个integer*/
  15.     int getval;
  16.     if(err != 0){
  17.         //调用失败的话,lua_pcall会push一个error code。很好。
  18.         printf("can not find corresponding getter\n");
  19.         getval = -1;
  20.     }
  21.     else{
  22.         getval = lua_tointeger(L, -1);
  23.         
  24.     }
  25.     lua_pop(L, 3);
  26.     lua_pushinteger(L, getval);
  27.     return 1;
  28. }
  29. /*prototype: userdata createDog(void)*/
  30. int createDog(lua_State *L){
  31.     struct dog *dog = lua_newuserdata(L, sizeof(struct dog));

  32.     luaL_newmetatable(L, "mtbl");
  33.     lua_pushstring(L, "__index");
  34.     lua_pushcfunction(L, getAttr);/**你搞清楚,这里已经是把c函数注册到lua的一个key里了,不用再lua_register()*/
  35.     lua_settable(L, -3);

  36.     lua_pushstring(L, "get");
  37.     lua_newtable(L);
  38.     lua_settable(L, -3);

  39.     lua_setmetatable(L, -2);

  40.     return 1;
  41. }

  42. int luaopen_cmodule(lua_State *L){
  43.     lua_register(L, "createDog", createDog);
  44.     return 0;
  45. }


点击(此处)折叠或打开

  1. Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
  2. > require"cmodule"
  3. > d=createDog()
  4. > mtbl=getmetatable(d)
  5. > mtbl.get.age = function() return 1234 end
  6. > print(d.agee)
  7. can not find corresponding getter
  8. -1
  9. > print(d.age)
  10. 1234
  11. >


阅读(1874) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~