28.5 Light Userdata

到目前为止我们使用的userdata称为full userdataLua还提供了另一种userdata: light userdata

一个light userdatum是一个表示C指针的值(也就是一个void *类型的值)。由于它是一个值,我们不能创建他们(同样的,我们也不能创建一个数字)。可以使用函数lua_pushlightuserdata将一个light userdatum入栈:

void lua_pushlightuserdata (lua_State *L, void *p);

尽管都是userdatalight userdatafull userdata有很大不同。Light userdata不是一个缓冲区,仅仅是一个指针,没有metatables。像数字一样,light userdata不需要垃圾收集器来管理她。

有些人把light userdata作为一个低代价的替代实现,来代替full userdata,但是这不是light userdata的典型应用。首先,使用light userdata你必须自己管理内存,因为他们和垃圾收集器无关。第二,尽管从名字上看有轻重之分,但full userdata实现的代价也并不大,比较而言,他只是在分配给定大小的内存时候,有一点点额外的代价。

Light userdata真正的用处在于可以表示不同类型的对象。当full userdata是一个对象的时候,它等于对象自身;另一方面,light userdata表示的是一个指向对象的指针,同样的,它等于指针指向的任何类型的userdata。所以,我们在Lua中使用light userdata表示C对象。

看一个典型的例子,假定我们要实现:Lua和窗口系统的绑定。这种情况下,我们使用full userdata表示窗口(每一个userdatum可以包含整个窗口结构或者一个有系统创建的指向单个窗口的指针)。当在窗口有一个事件发生(比如按下鼠标),系统会根据窗口的地址调用专门的回调函数。为了将这个回调函数传递给Lua,我们必须找到表示指定窗口的userdata。为了找到这个userdata,我们可以使用一个表:索引为表示窗口地址的light userdata,值为在Lua中表示窗口的full userdata。一旦我们有了窗口的地址,我们将窗口地址作为light userdata放到栈内,并且将userdata作为表的索引存到表内。(注意这个表应该有一个weak值,否则,这些full userdata永远不会被回收掉。)

 

 

 



相关链接:
lua程序设计目录 - 中国lua开发者 - lua论坛