Userdata of Lua
In Lua, you can use user data to interact with C code more efficiently and flexibly, thus extending the types that Lua can express.
Full userdata
Full userdata indicates an original memory block that can store anything. It is a table-like object that must be created in advance (or recycled by the garbage collector ), it also has its own retriable, which is only equal to its own.
You can create a unique meta table for each full userdata type to identify different types of userdata. Each time you create a userdata, you can use the corresponding meta table (in the Registry) to mark it, and each time a userdata is obtained, check whether it has a correct meta table.
When Lua releases the memory associated with full userdata, if it finds that the userdata meta table has the _ gc meta method, this method is called and passed in with userdata as a parameter. With this feature, you can recycle userdata and release resources associated with this userdata.
Create a full userdata:
Void * lua_newuserdata (lua_State * L, size_t size );
Lua_newuserdata allocates memory blocks of the specified size, then puts them into the stack, and returns the memory block address.
Lua does not pre-define any operations for user data. Therefore, the operation interfaces for user data are still provided by the C interface and registered to the Lua environment for Lua.
The following is an example of implementing a Boolean array using user data:
// Foo. c # include <lua. h> # include <lauxlib. h> # include <lualib. h> # include <limits. h> # define BITS_PER_WORD (CHAR_BIT * sizeof (int) # define I _WORD (I) (unsigned int) (I)/BITS_PER_WORD # define I _BIT (I) (1 <(unsigned int) (I) % BITS_PER_WORD) typedef struct NumArray {int size; unsigned int values [1];} NumArray; int newArray (lua_State * L) {int I, n; n = luaL_checkint (L, 1); luaL_argcheck (L, n> = 1, 1, "inva Lid size. "); size_t nbytes = sizeof (NumArray) + I _WORD (n-1) * sizeof (int); NumArray * a = (NumArray *) lua_newuserdata (L, nbytes ); a-> size = n; for (I = 0; I <I _WORD (n-1); ++ I) a-> values [I] = 0; lual_getretriable (L, "myarray"); lua_setretriable (L,-2); return 1;} int setArray (lua_State * L) {// 1. the first parameter that Lua passes to the function must be userdata, and the object metadata table must also be the table associated with myarray in the registry. // Otherwise, the function reports an error and terminates the program. NumArray * a = (NumArray *) luaL_checkudata (L, 1, "myarray"); int index = luaL_checkint (L, 2)-1; luaL_checkany (L, 3 ); // there are 3 arguments luaL_argcheck (L,! = NULL, 1, "'array' expected. "); luaL_argcheck (L, 0 <= index & index <a-> size, 2," index out of range. "); if (lua_toboolean (L, 3) a-> values [I _WORD (index)] | = I _BIT (index); else a-> values [I _WORD (index)] & = ~ I _BIT (index); return 0;} int getArray (lua_State * L) {NumArray * a = (NumArray *) luaL_checkudata (L, 1, "myarray "); int index = luaL_checkint (L, 2)-1; luaL_argcheck (L,! = NULL, 1, "'array' expected. "); luaL_argcheck (L, 0 <= index & index <a-> size, 2," index out of range "); lua_pushboolean (L, a-> values [I _WORD (index)] & I _BIT (index); return 1;} int getSize (lua_State * L) {NumArray * a = (NumArray *) luaL_checkudata (L, 1, "myarray"); luaL_argcheck (L,! = NULL, 1, "'array' expected. "); lua_pushinteger (L, a-> size); return 1;} int array2string (lua_State * L) {NumArray * a = (NumArray *) luaL_checkudata (L, 1, "myarray"); lua_pushfstring (L, "array (% d)", a-> size); return 1;} static luaL_Reg arraylib_f [] = {"new ", newArray },{ NULL, NULL }}; static luaL_Reg arraylib_m [] ={{ "set", setArray}, {"get", getArray}, {"size ", getSize}, {"_ tostring", array2string}, // pri When nt (a), Lua will call this metadata method. {NULL, NULL }}; int luaopen_foo (lua_State * L) {// 1. Create a metadata table and assign it to the userdata created by the newArray function. In Lua, userdata is also represented as a table. // When calling the object function, you can verify the name of its retriable to determine whether the parameter userdata is valid. Lual_newretriable (L, "myarray"); lua_pushvalue (L,-1); // 2. to implement the call method for objects, you need to point the _ index field of the metadatabase to itself, and then register the functions in the arraylib_m array to the // Metadatabase, then the call based on these registration functions can be called in the form of object-oriented. // Lua_setfield will pop up the table at the top of the stack after execution. Lua_setfield (L,-2, "_ index"); // register these member functions with the meta table to ensure that Lua can locate the function when searching for a method. The NULL parameter indicates that the second parameter will be replaced by the table at the top of the stack. LuaL_register (L, NULL, arraylib_m); // only the Factory method registered here. LuaL_register (L, "testuserdata", arraylib_f); return 1 ;}
Compiled into the C module to facilitate Lua call:
Gcc foo. c-shared-fPIC-o foo. so-llua-5.1-I/usr/local/include/
Use the Boolean array defined above in Lua:
Require "foo" local array = testuserdata. new (100) print (array: size () -- 100for I = 1,100 do array: set (I, I % 5 = 0) endfor I = 1,100 do print (array: get (I) end
In Lua, user data is used as a table.
Light userdata
Light userdata only represents the C Pointer (void *).
Light userdata is similar to the number type. It does not need to be created (it will not be recycled by the garbage collector), nor does it have a metadata table. It is equal to all light userdata that represents the same pointer;
Create a light userdata:
Void lua_pushlightuserdata (lua_State * L, void * p );
Userdata of Lua