第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于更高版本,但有一些区别。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目


28.5 – 轻量级用户数据

我们迄今为止一直在使用的用户数据称为完整用户数据。Lua 提供另一种用户数据,称为轻量级用户数据

轻量级用户数据是一个值,表示一个 C 指针(即一个 void * 值)。因为它是一个值,所以我们不会创建它们(就像我们不会创建数字一样)。要将轻量级用户数据放入堆栈,我们使用 lua_pushlightuserdata

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

尽管名称相同,但轻量级用户数据与完整用户数据有很大不同。轻量级用户数据不是缓冲区,而是单个指针。它们没有元表。与数字一样,轻量级用户数据不需要由垃圾回收器管理(也不会被管理)。

有些人使用轻量级用户数据作为完整用户数据的廉价替代品。然而,这不是典型用法。首先,对于轻量级用户数据,您必须自己管理内存,因为它们不受垃圾回收的约束。其次,尽管名称如此,但完整用户数据也很便宜。与给定内存大小的 malloc 相比,它们增加的开销很小。

轻量级用户数据的真正用途来自于相等性。由于完整用户数据是一个对象,因此它仅等于它自身。另一方面,轻量级用户数据表示一个 C 指针值。因此,它等于表示相同指针的任何用户数据。因此,我们可以使用轻量级用户数据在 Lua 中查找 C 对象。

作为一个典型的例子,假设我们正在实现 Lua 和窗口系统之间的绑定。在此绑定中,我们使用完整用户数据来表示窗口。(每个用户数据可能包含整个窗口结构或仅包含由系统创建的窗口的指针。)当窗口内发生事件(例如,鼠标单击)时,系统会调用特定回调,通过其地址识别窗口。要将回调传递给 Lua,我们必须找到表示给定窗口的用户数据。要查找此用户数据,我们可以保留一个表,其中索引是具有窗口地址的轻量级用户数据,而值是表示 Lua 中窗口的完整用户数据。一旦我们有了窗口地址,我们将其作为轻量级用户数据推入 API 堆栈,并使用用户数据作为该表中的索引。(请注意,该表应具有弱值。否则,这些完整用户数据将永远不会被收集。)