lua与c++的class绑定
来源:互联网 发布:java中的命令模式 编辑:程序博客网 时间:2024/06/06 17:00
一个naive的方法
static int newSprite(lua_State *L) { int n = lua_gettop(L); // Number of arguments if (n != 4) return luaL_error(L, "Got %d arguments expected 4", n); double x = luaL_checknumber (L, 1); double y = luaL_checknumber (L, 2); double dir = luaL_checknumber (L, 3); double speed = luaL_checknumber (L, 4); Sprite *s = new Sprite(Point2(x, y), dir, speed); lua_pushlightuserdata(L, s); return 1; }
非常简单的一个实现,可惜它并不能工作,因为lightuserdata只是一个指针,但是这东西在Lua脚本里并不被识别,也就不能直接使用。
一个基本符合要求的方法
既然不能直接使用lightuserdata,那么我们就使用user data数据嘛。它是带metatable的。
static int newSprite(lua_State* l) { int n = lua_gettop(l); if(n != 2) return luaL_error(l, "Got %d arguments expected 2", n); Sprite **s = (Sprite **)lua_newuserdata(l, sizeof(Sprite *)); int x = luaL_checknumber(l, 1); int y = luaL_checknumber(l, 2); *s = new Sprite(x, y); lua_getglobal(l ,"Sprite"); lua_setmetatable(l, -2); return 1;}
这里我们可以看到,它将全局变量的Sprite作为metatable绑定到新建的userdata元素(即是Sprite指针)。这个只是创建Sprite的绑定函数
static const luaL_Reg gSpriteFuncs[] = { {"new", newSprite}, {"getx", spriteX}, {NULL, NULL}};void registerSprite(lua_State *l){ luaL_register(l, "Sprite", gSpriteFuncs); //注册到Sprite Table lua_pushvalue(l,-1); // lua_setfield(l, -2, "__index"); }
接着我们定义绑定表。下面的registerSprite函数就是在指定的lua环境里,实现注册Sprite类。
首先注册了一个函数集到Sprite Table,这就是上面使用的Sprite全局变量。然后再复制一个Table,作为自身的__index属性。
local sprite = Sprite.new(1, 2)local posx = sprite:getx()print(posx)
所以Sprite.new()可以就是调用newSprite创建类实例,然后类实例会绑定Sprite作为自己的metatable,因为userdata不是table,所以__index是永远触发的,因为metatable是table,不是function,所以触发就会在metatable里找对应的元素,比如getx。然后它就会找到newSprite这个function元素。因为是通过”:”来触发的,所以会存在一个userdata的参数。
一个绝对完善的方法
上面的方法基本可以用的,但是如果你在Lua改变了一个sprite实例的方法,那么所有的sprite实例方法都会被改变。
在registry里创建一个表,叫做“Lusion.Sprite”,里面注册一堆函数。在复制一份这个metatable,将其作为其本身的__index属性。再重复注册一个Sprite函数集。
Lusion.Sprite(Funcs)->__index->Lusion.Sprite(Funcs)
在newSprite的时候,第一个参数是一张表,其实就是Sprite函数集的表。我们新建一张表,将Sprite作为它的metatable,并将__index属性设成Sprite自己。然后就新建一个userdata,获得Lusion.Sprite,把它作为userdata的metatable。把早前建的新表的__self域指向userdata,将新表返回。结果如下所示:
table-->metatable->Sprite->__index->table |->__self->userdata->metatable->Lusion.Sprite
读取的时候,就先通过table获得__self的值,然后通过self的值读取userdata,获得指针
这种方法为什么可以解决上面的问题呢。因为在new实例的时候,table是新建的,metatable里面保存了自己的函数。我还不是很理解为什么Lusion.Sprite需要链接自己,说不定是为什么destroy的时候用的。
- lua与c++的class绑定
- vue中style与class的绑定
- vue的Class 与 Style 绑定
- Vue的Class 与 Style 绑定
- Class 与 Style 绑定
- lua 与c的交互
- Lua与C的交互
- Lua与C的交互
- lua与c的交互
- C与Lua的交互
- Lua的与C交互
- cocos2dx的lua绑定
- cocos2dx的lua绑定
- cocos2dx的lua绑定
- cocos2dx的lua绑定
- Cocos2dx-- Lua与C++绑定
- cocos2dx lua与c++绑定
- cocos2dx3.0下sqlite的C++与lua绑定
- JAVA学习笔记之(三)流程控制
- 字符编码格式总结 (参考手册)
- mysql-sql语句中变量的使用
- 剑指offer:数组中的逆序对
- 大数据(十四)Hadoop-MR编程 -- 【使用hadoop计算网页之间的PageRank值----概念】
- lua与c++的class绑定
- 九度1042:Coincidence
- redis3.0.0 集群安装详细步骤
- 项目开发流程
- python装饰器详解
- 利用Ret2Libc挑战DEP之二——利用VirtualProtect
- CentOS6.5安装Xen
- 三(1)、JSP九大内置对象——out
- Low-level GPU programming