save state in C function: Registry, reference, and Upvalues
C functions can exchange data with Lua through the stack, but sometimes C functions need to save some LUA data outside the scope of the function body, so we think of global variables or static variables, and the disadvantage is:(1) When designing a C function library for LUA, it is not possible to re-enter, (2) Not all LUA values are well preserved in C variables. can you save the value in the LUA global variable, then LUA provides a separate table called registry, but the LUA code itself cannot access it.
1. Registry Global Registry
Explanation: An ordinary LUA table, accessed using a false index (PSEUDO-INDEX)Lua_registryindex. C code can be accessed, and LUA code cannot access it.
Purpose: Solves the problem of preserving global LUA values for C functions.
Note: All C libraries share the same registry, so the naming of keys requires global uniqueness.
Method for obtaining the value of the registry table key value "key": lua_pushstring (L, "key"); Lua_gettable (L, Lua_registryindex);
2, reference reference system
explanation: A LUA data object is uniquely identified by an integer , consisting of two functions lual_ref and Lual_unref, This pair of functions is used to do not need to worry about name collisions to save the values to registry.
purpose: Store a reference that points to the LUA value in a C struct, which is a key of int.
Note: When the stack top value is nil, no reference,lual_ref function will return Lua_refnil, and the Lua_refnil dereference is ineffective.
important functions:
int lual_ref (lua_state *L, int t);
Create and return a reference reference and add [reference, stack top value v] to the table corresponding to T.
void lual_unref (lua_state *l, int t, int ref);
dereference, delete the [reference,v] key value pair in the table corresponding to T.
A reference to the value V of the top of the stack is generated, and the [R, v] is stored in the Lua_registryindex table int r = lual_ref (L, lua_registryindex); Put a reference value into the stack lua_rawgeti (L, Lua_registryindex, R); dereference, i.e. release reference and value lual_unref (L, Lua_registryindex, R);
3. Upvalues mechanism
Explanation: When you create a C function, you can associate some values so that a C closure is created, and these values are called upvalues.
Purpose: Implements the concept of equivalence with C static variables, which can only be visible within a specific function.
Use: to generate false indexes by Lua_upvalueindex (n) to access.
Pre-declared static int counter (lua_state *l); Create a factory function for C closures int newcounter (lua_state *l) { lua_pushnumber (L, 0); Lua_pushcclosure (L, &counter, 1); return 1; } c function static int counter (lua_state *l) { double val = lua_tonumber (L, Lua_upvalueindex (1)); Lua_pushnumber (L, ++val); /* New value * /Lua_pushvalue (L,-1); /* Duplicate it * /Lua_replace (L, Lua_upvalueindex (1)); /* Update Upvalue */ return 1; /* Return new value */ }
Note: Never use a number as registry key, because this type of key is reserved for use by the reference system.
False index (PSEUDO-INDEX) features: (1) The corresponding value is not in the stack, (2) is used similar to the stack index, most of the functions that accept the index as parameters can be used; (3) The functions of the stack itself cannot use false indexes, such as Lua_remove,lua_insert.
Unlike LUA closures (in LUA code, a closure is a function that accesses local variables from an external function ), C closures cannot share upvalues: each closure has its own set of variables. However, we can set the upvalues of different functions to point to the same table, so that the table becomes a place where all functions share data.
Save state in C function: Registry, reference, and Upvalues