I'm using userdata for passing things around with metatables in Lua and calling c++. I'm wondering if maybe light userdata can help me with a few problem cases I have.
A light userdata is a void *, but you can't do anything with it in lua, at least thats my understanding you can just pass it around and back to C somehow - by a function call?.
How do you use a light userdata? If anyone has some use cases they've used them for it would help me get my head around them.
tia
I think Programming In Lua explains it quite well:
The real use of light userdata comes from equality. As a full userdata is an object, it is only equal to itself. A light userdata, on the other hand, represents a C pointer value. As such, it is equal to any userdata that represents the same pointer. Therefore, we can use light userdata to find C objects inside Lua.
As a typical example, suppose we are implementing a binding between Lua and a Window system. In this binding, we use full userdata to represent windows. (Each userdatum may contain the whole window structure or only a pointer to a window created by the system.) When there is an event inside a window (e.g., a mouse click), the system calls a specific callback, identifying the window by its address. To pass the callback to Lua, we must find the userdata that represents the given window. To find this userdata, we can keep a table where the indices are light userdata with the window addresses and the values are the full userdata that represent the windows in Lua. Once we have a window address, we push it into the API stack as a light userdata and use the userdata as an index into that table. (Note that the table should have weak values. Otherwise, those full userdata would never be collected.)
The page also explains that light userdata is not garbage collected so memory management must be done by your code. It seems to me the use cases are actually fairly limited which is probably why you can't find many examples. I did find one example:
I have a routine that constructs a gui object (tree view) from a lua table. I then have a seperate lua table indexed by the window handle of each tree node, as a lightuserdata. This simplifies the c/lua interface - i can use the c handle to lookup the appropriate lua table object.
// save a window handle
lua_pushlightuserdata(L, hKey);
lua_pushvalue(L,filt); // copy of filter table entry
lua_settable(L, treeindex);
// find data for a window handle
lua_pushstring(L, "__treeitems");
lua_gettable(L, LUA_GLOBALSINDEX);
lua_pushlightuserdata(L, hKey);
lua_gettable(L, -2);
A typical use case is when you're embedding lua into another application, and you want to give lua authors tokens (in the form of light user data) that they can pass to the API you set up. Here's a specific example.
Say you provided the following API in lua for people and friends:
These would give you access to 'friend' objects through your bindings
GetPersonCount() // returns a number
GetPerson(index) // returns a light user data - a pointer to the C++ version
These would take the return value of GetPerson (or GetFriend below) as an argument.
GetFirstName(person)
GetLastName(person)
GetFriendCount(person)
GetFriend(person, index) // would also return user data like GetPerson
This would be useful if you've already built a program in C++ for getting information about friends, but you want to make it available to people writing scripts in lua through a more simple and limited interface that can be accessed at runtime safely without requiring compilation or your source code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With