Lua closure in detail from ringofthec[ring.of.the.c@gmail.com]

Source: Internet
Author: User

These things are encountered at ordinary times, feel that there is a certain value, so recorded, and later encountered similar problems can be consulted, at the same time to share the people can be easily needed, reproduced please specify from Ringofthec[[email protected]]

Here, simply record the knowledge of the closures in Lua and the C closure call

Prerequisite knowledge: In LUA API 2 has analyzed the structure of the value of Lua, is a tvalue{value, TT} combination, if in doubt, you can go to see

Some of the important data structures

There are two types of closures in Lua, c closures and LUA closures

The public part of two closures:

#define Closureheader Commonheader;        Lu_byte IsC; Lua_byte nupvalues;       gcobject* gclist; struct Table env

/* is the number of C closures *//*upval *//////* closed env, SET/GETENV is manipulating it */

Structure of the C closure package

struct cclosure{

Closureheader;

Lua_cfunction F;

TValue Upvalue[1];

}

The structure is relatively simple, f is a C function that satisfies the type of int lua_func (lua_state*)

Upvalue is the upvalue that is pressed when the C closure is created, the type is TValue, and you can tell that Upvalue can be any LUA type

LUA Closure structure

struct lclosure{

Closureheader;

Strcut proto* p;

upval* Upvals[1];

}

The structure of the proto is rather complicated, so we don't analyze it first.

A unified closure structure, a consortium, shows that a closure is either a C closure or a LUA closure, which is identified by the ISC form.

Union closure{

Cclosure C;

Lclosure l;

}

Tangle of closures

Why do we call closures, not functions, it looks like a function? Why do you invent a "closure" that sounds like an egg-sore word? I also tangled in here for a long time, probably almost 1.5 ~~~=.= I am more stupid ~ ~ ~ with the look at the source, now figured out, take out some of their own in the study process of experience [as far as possible to understand]:

1. Definition of function in C: abstract block of function, this is no objection.

2. Lua extends the function:

A. Several values and functions can be bound together, and these values are called Upvalue.

PS: Some people may think that C + + function objects can also bind a few values and functions ah, this is the case, but this problem is like "in the assembly can also achieve object-oriented ah", LUA from the language level to support the Upvalue, like C++/java from the language level provides the class, The support of the object, of course, greatly frees the workload of our programmers, and with the LUA dynamic type, it is a lot easier for people.

B. Each function can be bound to an env (environment).

PS: If the above upvalue can also be coding in C + +, then the env context is unique in the dynamic language C + + there is no obvious corresponding structure it? Maybe some people think that Lua is written in C, through coding can also be achieved, well =.=, "can Do and do" is not the same thing, I think you can walk from Beijing to Shanghai, do not show that you have to do so. Env is a very important and useful thing, it can easily create a restricted environment, is the legendary "sandbox", I said more popular is "a dynamic namespace mechanism." This is not analyzed for the time being.

Well, now we see

C function {function abstract}

Lua Closures {function abstraction, Upvalue, env}

Focus: Closures = = {Functional abstraction, Upvalue, env}

 

See here, we all understand, if the LUA {function abstract, Upvalue, env} also known as function, not only easy to arouse everyone's misunderstanding that it is the same as the C function, and it does not really well express the rich connotation of LUA functions, closures, "closed" It is an object, a visible and tangible thing, an indivisible whole (first Class); "Package" means that it contains the function abstraction, Upvalue, env. a very interesting fact here is that {functional abstraction, Upvalue, env} is an implementation feature of many dynamic languages, such as Lua, where JavaScript implements such a structure, which is implemented first and then named "Closure".  So, you just want to understand the word closure, basically there is no way to understand, to go online check closures, useless, you can find a few examples using closures, after reading to ensure that your feeling is "this thing is very mysterious, but still do not understand what is closure", why do not understand? Because it refers to the implementation of structural features, it is to implement the function first class and the context concept in the dynamic language created.

Better to say a few words, as long as it is good to deepen the understanding of the line, there are two sentences "I ride to buy some fruit" "I use closures {function abstraction, Upvalue, env} to implement function first class and context concepts in dynamic languages", closures and "cycling" are a means of achieving your goal, In order to buy fruit, you think of the idea of "cycling" is not to buy fruit for cycling. It's not right to keep your eyes on the bike, it's just a means.

The process of registering a C function with Lua is achieved through the lua_pushcclosure (L, F, N) function.

Process: 1. Create a sizeof (cclosure) + (n-1) * sizeof (TValue) size of memory, this memory is Cclosure + tvalue[n], and do GC bookkeeping [This is too important why LUA controls its own world There is a variable, because it wants to do GC bookkeeping to manage memory], isc= 1 indicates that it is a C closure.

2. c->f = f binds the C function. --------- closures. Functional abstraction = f

3. env = env[of the current closure This indicates that the created closure inherits the environment where it was created]. ----------- closures. env = env

4. Assign n elements on the stack to the c->upvalue[] array, in order that the value of the first stack is placed at the beginning of the Upvalue array, c->nupvalues specifies the number of Upvalue to change the closure. ---------- closures. Upvalue = Upvalue

5. Eject the n elements on the stack and press into the new closure to the top of the stack.

The whole process is relatively simple, allocating memory, filling in attributes, chaining into GC monitoring, binding C functions, binding upvalue, binding env A C closure is OK, please combine the above to explain the closure, very clear.

Now to parse the procedure called by the C closure [note that only C closures are involved in this call]

LUA Closure Call information structure:

struct Callinfo {
Stkid Base; /* Base for this function */----the stack base of the closure call
Stkid func; /* Function index in the stack */----The position of the closure to be called on the stack
Stkid top; /* Top for this function */----closure of the stack use limit, is lua_push* time to look at the point, push too much is super, can lua_checkstack to expand
const instruction *SAVEDPC; ----If another closure is called again in this closure, the value saves the next instruction to continue execution on return
int nresults; /* Expected number of results from this function */----closure to return the value of
int tailcalls; /* Number of tail calls lost under this entry * *----tail recursion, temporarily regardless
}

As can be seen from the note, this structure is relatively simple, its role is to maintain a function call information, in fact, and the C function call stack frame is the same, the important information base–> EBP, func–> to invoke the function of the stack index, savedpc–> EIP, Top, nresults and tailcalls have no apparent correspondence.

at the time of Lua initialization, a callinfo array is assigned, and L->base_ci points to the first element of the array, with l->end_ci pointing to the last pointer to the array, using L->SIZE_CI to record the current size of the array, L- >CI records the invocation information of the currently called closure.

Here's a procedure for calling a C closure:

Scenario: C function int lua_test (lua_state* L) {

int a = Lua_tonumber (L, 1);

int b = Lua_tonumber (L, 2);

A = a + B;

Lua_pushnumber (L, a);

}

is already registered in Lua, forming a c closure, named "Test," and then calling it.

Lual_dostring (L, "c = Test (3, 4)")

1. First, we translate it into the corresponding C API

1. The initial stack

Lua_getglobal (L, "test")

Lua_pushnumber (L, 3)

Lua_pushnumber (L, 4)

2. Stack of functions and parameters pressed into

Lua_call (L, 2, 1)

3. Call the stack at the beginning of lua_test

4. Call the end of the stack

Lua_setglobal (L, "C")

5. Take out the stack of the call result

The main point we want to know is the process of the Lua_call function.

1. The consistency of LUA here again is shocking, whether it is dostring, or dofile, will form a closure, that is, the closure is used in LUA to organize the structure of the basic components, this feature makes the structure in Lua is consistent, is a concise and powerful concept.

2. According to 1, a = Test (3, 4) is actually organized into a closure on the top of the LUA stack [for convenience, the LUA closure is named BB], it is said that dostring really called the BB closure, and then the BB closure is called test

[Save current information to Callinfo in current function]

3. At the time of the call to test, L->CI records the call information for the BB closure, so the next instruction to be executed is placed in the L->CI->SAVEDPC for execution after returning from Test.

4. Take the test C closure CL on the stack, using Cl->isc = = 1 To determine that it is indeed a C-closed packet

[Enter a new Callinfo, lay the stack]

5. A new Callinfo CI is assigned from L to record the call information of test and set its value to L->ci, which indicates that a new function call has begun, here also specify the position of test in the stack, l->base = Ci->base = ci-& Gt;func+1, note that these assignments are important, resulting in the stack state from Figure 2 to Figure 3, as you can see, l->base points to the first parameter, Ci->base also points to the first parameter, so in test, we call Lua_ The value returned by the GetTop function is 2, because when it is called, it has only 2 elements on its stack frame, which implements LUA's transfer of parameters to the C language.

[Invoke the actual function]

6. Arrange the stack, the following is based on the L->ci->func point to the stack on the closure (and test C closure), find the corresponding cl->c->f, and call, entered the C function lua_test

[Get Return value adjustment stack, return to original Callinfo]

7. Based on the return value of the lua_test, the test closure and parameters pop-up stack, and the return value is pressed into and adjusted l->top

8. Restore L->base, L->ci and L->SAVEDPC, and continue with the execution.

Summary: Call a new closure when 1. Saves the current information to the current function in Callinfo 2. Enter a new callinfo and lay out the stack 3. Call the actual function 4. Gets the return value of the adjustment stack, returning the original Callinfo

A short continuation was written for 6 hours ... First write here, right, I began to write a blog soon, and limited ability to express, if you want to see the essence, discard the dross it:)

Lua closure in detail from ringofthec[ [email  Protected] ]

Related Article

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.