Light userdata, like heavy userdata, are a form of userdata, which is one of the basic data types in Lua [1]. Light userdata are characterized by the following properties:
- Light userdata and heavy userdata have deceptively similar names, and both have the property
type(x) == 'userdata'
, but these two forms of userdata are otherwise quite different in behavior [1], as outlined below.
- A light userdatum represents a single pointer to a physical memory address (void *), which is typically a 32- or 64-bit value depending on platform. Light userdata are intended to store C pointers in Lua (note: Lua numbers may or may not be suitable for this purpose depending on the data types on the platform).
- A heavy userdatum represents a region of mutable bytes allocated in Lua's memory and managed by Lua (garbage collected). This is the only memory in Lua that you are permitted to read/write directly from C (via the userdata's pointer) without the C API.
- Light userdata have the semantics of values, while heavy userdata have the semantics of objects. Objects have a unique identity [2]: Two heavy userdata constructed with the same data will always be distinguishable (e.g.
rawequal
will differentiate them by memory address); two light userdata so constructed will never be distinguishable because they are compared by value not by address.
- Light userdata (unlike heavy userdata) are not garbage collected. LuaImplementations typically fit each light userdatum in a single register and copy them around by value, while heavy userdata is allocated on the heap and passed around by reference (pointer).
- Equality: If
x
is a lightuserdatum, then x == y
if-and-only-if y
is a light userdatum representing the same pointer. Light userdata can be used as table keys, in which case x == y
implies t[x]
and t[y]
refer to the same table value (though not necessarily that t[x] == t[y]
since NaN ~= NaN). The __eq
metamethod has no effect on light userdata (note: the manual isn't clear on this [1]).
- Light userdata (unlike heavy userdata) have no per-value metatables. All light userdata share the same metatable, which by default is not set (
nil
).
-
tostring(x)
typically displays the pointer in hex notation, although this is specific to LuaImplementations.
Some interesting points:
- A common technique for mapping C pointers to Lua values is to store a light userdata of that pointer as a key in the registry table. [Reference Manual, 3.5]. Bear in mind that these mapping are not automatically garbage collected [3], and you might want to use a weak table rather than the registry (which by default is not weak, but a weak table can be stored in it).
- Some people represent handles rather just pointers as lightuserdata [4]. It's possible to represent other data in them as well [5]. Take care not to mix pointer and non-pointer userdata in a way that might conflict (e.g. storing both in the registry table).
- Light userdata are created from the C API via [lua_pushlightuserdata]. Out-of-the-box, Lua doesn't provide a way to create lightuserdata from Lua.
- A one-page summary of light userdata is provided in [1].
--DavidManura
See Also
- [1] ProgrammingInLua?, Section 28.5 "Light Userdata".
RecentChanges · preferences
edit · history
Last edited August 4, 2011 2:56 am GMT (diff)