[Lua] Save state in C function--Registry, environment table, Upvalue

Source: Internet
Author: User

What is it called in the C function to save the state? For example, you are now using LUA to invoke the C function Func1, but some of the data in Func1 is saved for later use after the call is finished. And that data is the so-called state, which is what we need to preserve. Someone will say, when Lua calls C, all the states that need to be saved are returned to Lua, and when the next function is called, the required state is passed in as a parameter, which is a good way, but it is troublesome. Method one: Registry; method two: Environment; method Three: Upvalue.
The registry is a global table that can only be accessed by C code. In general, it can be used to save data that needs to be shared among several modules;
However, if you need to save a module's private data, then you should use the environment, like the LUA function, each C function has its own environment table, typically, all functions within a module share the same environment table, so that they can share data.
Finally, the C function can also have upvalue,upvalue, which is a LUA value associated with a particular function.

Registration FormThe registry is always located on a "pseudo index", which is defined by Lua_registryindex. A pseudo-index is like an index in a stack, but the value associated with it is not in the stack; What do you think of the end of the sentence? In C + +, using new to open space, this space is created on the heap, and the variables that point to the heap are stored on the stack. Pseudo-index is similar to this meaning. Most functions in the Lua API can accept pseudo-indexes, but functions such as lua_remove and Lua_insert can only use normal indexes.
The registry is a normal LUA table that can be indexed with any LUA value (except nil).
#include <iostream>using namespace std; #include <lua.hpp>void registrytestfunc (lua_state* L) {    Lua_ Pushstring (L, "Hello");    Lua_setfield (L,lua_registryindex, "Key1");    Lua_getfield (L,lua_registryindex, "Key1");    printf ("%s\n", Lua_tostring (l,-1));//output is: Hello}int main () {    lua_state* L = Lual_newstate ();    Registrytestfunc (L);    Lua_close (L);    return 0;}
Environment tablestarting with 5.1, all C functions registered in LUA have their own environment table. A function can access its environment by using a pseudo-index like the registry to access the table. The pseudo-index of the environment table is lua_environindex.
This approach to using the environment is similar to using the environment in the LUA module by creating a new table for the module and then sharing the table with all the functions in the module. Only a setfenv function is used in Lua, and in the C module it is simply setting table to Lua_environindex

#include <iostream>using namespace std; #include <lua.hpp>int setValue (lua_state* L) {    Lual_ Checkstring (l,-1);    Lua_pushvalue (l,-1);    Lua_setfield (L,lua_environindex, "Key1");    return 0;} int GetValue (lua_state* L) {    Lua_getfield (l,lua_environindex, "Key1");    return 1;} Static Lual_reg myfuncs[] = {{"     setValue", SetValue},    {"GetValue", GetValue},    {null, null}}; extern "C" __de Clspec (dllexport)  int luaopen_testenv (lua_state* l) {    lua_newtable (l);  Create a new table for the Environment    Lua_replace (L,LUA_ENVIRONINDEX);//Replace the new table that you just created and pressed into the stack with the current module's environment table.    Lual_register (L, "testenv", Myfuncs);    return 1;    This registration function takes two more lines of code than the previously written registration function, first creating a new table, and then calling Lua_replace to make the new table the Environment table. When you call Lual_register, all new functions inherit the current environment. }
Test.lua File Contents
Require "testenv" local fun1 = function ()    local var = "Hello,world!!!"    Testenv.setvalue (Var)    print (Testenv.getvalue ())-Output Hello,world!!! Endxpcall (Fun,print) os.execute ("Pause")
first, set the value to the module environment table. And then remove it from it. This has a lot in common with the above-mentioned registry. Although the environment may be used in place of the registry, if there is no need to share data between different modules, as far as possible do not use the registry, the use of environment-created references, only in this module is visible, so that the use of data to reduce the scope of the application of data, reducing the possibility of error, increased data security. UpvalueUpvalue is associated with a particular function, and we can simply interpret it as a static variable within a function.
The registry provides the storage of global variables, the environment provides the storage of module variables, and the upvalue mechanism implements a mechanism similar to static variables in C language. And this upvalue mechanism allows us to define a variable that is visible only in a particular function. Whenever you create a function in Lua, you can associate any number of Upvalue with this function. Each upvalue can hold a LUA value. Later, when this function is called, the Upvalue can be accessed through a pseudo-index. This association of C functions with Upvalue is called closure (also known as closures, how familiar names are). A c closure is similar to LUA closure. Closure can use the same function code to create multiple closure, each closure can have a different upvalue.
#include <iostream>using namespace std; #include <lua.hpp>int counter (lua_state* L) {    //Gets the value of the first upvalue.    int val = Lua_tointeger (L,lua_upvalueindex (1));    The resulting results are pressed into the stack.    Lua_pushinteger (l,++val);    Assigns a copy of the data at the top of the stack for subsequent substitution operations.    Lua_pushvalue (l,-1);    This function replaces the data at the top of the stack with the value in Upvalue (1). The stack top data is also ejected.    Lua_replace (L,lua_upvalueindex (1));    The data pressed in Lua_pushinteger (L,++value) remains in the stack and is returned to Lua.    return 1;} int Newcounter (lua_state* L) {    //press into the initial value of a upvalue of 0, the function must be called before lua_pushcclosure.    Lua_pushinteger (l,0);    Pressed into the closure function, parameter 1 represents the number of upvalue of the closure function. The function returns a value, and the closure function is always at the top of the stack.    lua_pushcclosure (l,counter,1);    return 1;} Static Lual_reg myfuncs[] = {{"     counter", counter},    {"Newcounter", Newcounter},    {null, null}}; extern "C "__declspec (dllexport)  int luaopen_testupvalue (lua_state* l) {    lual_register (L," Testupvalue ", Myfuncs);    return 1;}
Test.lua File Contents
Require "testupvalue" local fun = function ()    func = Testupvalue.newcounter ();    Print (func ());    Print (func ());    Print (func ());    Func = Testupvalue.newcounter ();    Print (func ());    Print (func ());    Print (func ());    --[[output:    1    2    3    1    2    3    --]]endxpcall (fun,print) os.execute ("Pause")

[Lua] Save state in C function--Registry, environment table, Upvalue

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.