The interactive detailed _lua of Lua and C language

Source: Internet
Author: User
Tags garbage collection lua new set

Objective

The basics of LUA have finally come to an conclusion, and from this post we are truly entering the LUA world, a boring and interesting world. Come on.

The LUA language is an embedded language, its power is limited; When Lua meets C, it shows its power. C and Lua can be invoked with each other. The first is that the C language has control, and Lua is a library in which the C code is called "Application code"; In the second case, LUA has control, and C is a library, at which point C code is "library code." Both "Application code" and "library code" use the same APIs to communicate with Lua, which is called the C API.

The C API is a set of functions that enable C code to interact with LUA, including many operations on the LUA code. How to operate, what to operate, our article I will one by one summary. The C API is very flexible and powerful. In order to show its NB, not first to a small demo program to show, how can it do?

Copy Code code as follows:

#include <iostream>
#include <string.h>

extern "C"
{
#include "Lua.h"
#include "Lauxlib.h"
#include "Lualib.h"
}
int main ()
{
Char buff[256] = {0};
int error;
Lua_state *l = Lual_newstate (); Open Lua
Lual_openlibs (L); Open Standard Library
while (fgets (buff, sizeof (buff), stdin)!= NULL)
{
Error = Lual_loadbuffer (L, Buff, strlen (buff), "line")
|| Lua_pcall (L, 0, 0, 0);
if (Error)
{
fprintf (stderr, "%s", Lua_tostring (L,-1));
Lua_pop (L, 1); Eject error message from stack
}
}

Lua_close (L);
return 0;
}

If you have not contacted the C API, for the above code, you certainly do not understand what it is doing. Don't say anything, you run it. Then enter the LUA statement to see the results of the operation.

Explain the first few header files introduced in the above code:

Header file lua.h defines the underlying functions that LUA provides, including creating LUA environments, calling LUA functions, reading and writing global variables in the LUA environment, and registering new functions for LUA calls, and so on;

The header file lauxlib.h defines the auxiliary functions provided by the secondary library, and all its definitions begin with Lual_. A secondary library is a higher level of abstraction that is written using APIs in Lua.h. All of the standard libraries in Lua are written in a secondary library, and the secondary library is primarily used to solve actual problems. The secondary library does not directly access the internals of LUA, and it does all the work with an official base API;

Header file Lualib.h defines a function that opens a standard library. No global variables are defined in the LUA library. It saves all States in the dynamic structure lua_state, and all the C APIs require a pointer to that structure to be passed in. The Lual_newstate function is used to create a new environment or state. When Lual_newstate creates a new environment, the new environment does not contain predefined functions (Eg.print). To keep Lua flexible and compact, all of the standard libraries are organized into different packages. When we need to use which standard library, we can call the function defined in lualib.h to open the corresponding standard library, while the auxiliary function lual_openlibs can open all the standard libraries.

Header file said, if the code in the extern "C" do not understand the classmate, please see here. Then, there is no then, and then I will not explain, and so I summed up the contents of the following, and then look back, you will understand more thoroughly. Click here to download the complete project engineering.

Stack

The main method for Lua and C language communication is a ubiquitous virtual stack. Almost all API calls manipulate the values on the stack, and all data exchanges, whether Lua to C or C, to Lua, are done through this stack. Stacks address the two major differences between LUA and C, the first of which is that Lua uses garbage collection, while the C language requires that memory be explicitly freed, and the second is that LUA uses dynamic types, while the C language uses static types.

To shield the difference between C and Lua, the virtual stack appears as the interaction between the two becomes common. Each element of the stack can hold any type of LUA value, when you want to get a value in Lua in C code, just call a LUA API function, and LUA pushes the specified value into the stack, and when you pass a value to LUA, you need to push that value into the stack, and then call the LUA API, Lua gets the value and pops it out of the stack. To push the value of type C into the stack, or to get different types of values from the stack, you need to define a specific function for each type. Yes, that's what we did.

LUA operates the stack strictly according to the LIFO specification. But when you call Lua, LUA only changes the top of the stack. However, the C code has more freedom, it can retrieve the elements in the middle of the stack, or even insert or delete elements anywhere on the stack.

Press into Stack

For each C type that can be rendered in Lua, the API has a corresponding push function, which I have listed here:

Copy Code code as follows:

void Lua_pushnil (Lua_state *l);
void Lua_pushboolean (lua_state *l, int bool);
void Lua_pushnumber (Lua_state *l, Lua_number N);
void Lua_pushinteger (Lua_state *l, Lua_integer N);
void Lua_pushlstring (lua_state *l, const char *s, size_t len);
void Lua_pushstring (lua_state *l, const char *s);

The above function is very simple, from the name can know what they mean. There's not much to say here. A detailed example code is provided for your reference later. Since this stack is not infinitely large, when you press an element into the stack, you should ensure that there is enough space in the stack. When Lua starts, or when Lua calls the C language, there will be at least 20 free slots in the stack. These spaces are generally sufficient, all of us are generally not considered, but there will always be special cases, if you call a function with many parameters, you need to call Lua_checkstack to check whether there is enough space in the stack.

Query element

The API uses indexes to stack elements. The first push-into-stack element is indexed to 1, the second pressed element is 2, and so on, up to the top of the stack. We can also use the top of the stack as a reference, using negative numbers to access the elements of the stack, at this point,-1 for the top of the stack,-2 for the bottom of the stack elements, and so on. Some situations are suitable for using positive index, and in some cases it is suitable to use negative index, we can flexibly adapt according to actual demand.

To check whether an element is a specific type, the API provides a series of function lua_is*, where * can be any LUA type. These functions have Lua_isnumber, lua_isstring, and lua_istable, all of which have the same prototype:

Copy Code code as follows:

int lua_is* (lua_state *l, int index);

In fact, Lua_isnumber does not check whether a value is a numeric type, but instead checks whether the value can be converted to a numeric type. Lua_isstring has the same behavior, so there's a situation where lua_isstring always returns true for values that can be converted to string, so lua_is* such functions are not very convenient when used, so there is a Lua_ Type function that returns the type of the elements in the stack, each of which corresponds to a constant light, often defined in the header file Lua.h, which is:
Copy Code code as follows:

/*
* * Basic Types
*/
#define Lua_tnone (-1)
#define LUA_TNIL 0
#define Lua_tboolean 1
#define LUA_TLIGHTUSERDATA 2
#define Lua_tnumber 3
#define LUA_TSTRING 4
#define Lua_ttable 5
#define Lua_tfunction 6
#define LUA_TUSERDATA 7
#define Lua_tthread 8

You can also use this function if you want to check whether an element is a true string or a number (without conversion).

Take value

We typically use the lua_to* function to get a value from the stack, with the following commonly used value functions:

Copy Code code as follows:

Lua_number Lua_tonumber (lua_state *l, int idx);
Lua_integer Lua_tointeger (lua_state *l, int idx);
int Lua_toboolean (lua_state *l, int idx);
const char *lua_tolstring (lua_state *l, int idx, size_t *len);
size_t Lua_objlen (lua_state *l, int idx);
Lua_cfunction lua_tocfunction (lua_state *l, int idx);
void *lua_touserdata (lua_state *l, int idx);
Lua_state *lua_tothread (lua_state *l, int idx);
const void *lua_topointer (lua_state *l, int idx);

If the specified element does not have the correct type, calling these functions will not be problematic. In this case, Lua_toboolean, Lua_tonumber, Lua_tointeger, and Lua_objlen return 0, while the other functions return null. The lua_tolstring function returns a pointer to a copy of the internal string and stores the length of the string in the last parameter Len. This internal copy cannot be modified, and the const in the return type illustrates this. LUA guarantees that the pointer is valid as long as the corresponding string is still in the stack. When a C function called by Lua returns, LUA empties its stack. Here's a very important rule:

Copy Code code as follows:

Do not use the pointer to the LUA string obtained in the C function outside of the C function * * *

The string returned by all lua_tolstring will have an extra 0 at the end of the string, but there may be 0 in the middle, and the length of the string is returned by the third parameter Len, which is the true string length.

The Lua_objlen function can return the "Length" of an object. For strings and table, this value is the result of the length operator "#". This function can also be used to get the size of a "fully userdata", which will be summarized separately for UserData.

Other stack operations

In addition to functions that exchange data between the C language and the stack, the API provides the following functions for ordinary stack operations:

Copy Code code as follows:

/*
* * Basic Stack manipulation
*/
int Lua_gettop (lua_state *l);
void Lua_settop (lua_state *l, int idx);
void Lua_pushvalue (lua_state *l, int idx);
void Lua_remove (lua_state *l, int idx);
void Lua_insert (lua_state *l, int idx);
void Lua_replace (lua_state *l, int idx);

Now to simply say these functions, the Lua_gettop function returns the number of elements in the stack, or the index of the top element of the stack. Lua_settop sets the top of the stack to a specified location. That is, to modify the number of elements in the stack, if the previous stack is higher than the new set, then the higher these elements will be discarded, on the contrary, the stack will be pressed into the nil to complement the size; For example, call the following statement to empty the stack:

Copy Code code as follows:

Lua_settop (L, 0);

You can also use a negative index to use Lua_settop. The Lua_pushvalue function pushes a copy of the specified index onto the stack. Lua_remove deletes the element on the specified index and moves all elements above the position to fill the vacancy. Lua_insert moves all elements above the specified position to create a slot and then moves the top element of the stack to that position. Lua_replace the value of the top of the pop-up stack and sets the value to the specified index, but it does not move anything, but replaces the value of the specified index. Said so much, summed up so much, not to point real gun work, always feel very virtual, on the code. Click here to download all the code works in this blog post.

What if the C API goes wrong?

No perfect, no bugs in the program. Yes, again NB of people write procedures, there may be problems, some problems are not within our control. Since we can't control the problem, we deal with the behavior after the problem arises, such as having a problem, popping up a friendly message, which sounds good, and many programs do so. All right, man, what if the C API goes wrong?

All of the structures in Lua are dynamic, and they grow or shrink as needed. Yes, the growth is narrowing, it involves the opening up and release of memory, which may be wrong, although I know the probability is very low, but for programmers, for any possible problems in the place to deal with. Here are two things:

1.C calls the LUA code;
2.Lua code calls C.

Not all API functions throw exceptions. Functions Lual_newstate, Lua_load, Lua_pcall, and lua_close are all safe. In the first case, it is generally used Lua_pcall to run the LUA code, because Lua_pcall runs the LUA code in a protected situation, and if a memory allocation error occurs, Lua_pcall returns an error code and marshals the interpreter in a consistent state If you want to protect the C code that interacts with LUA, you can use Lua_cpcall, a function similar to Lua_pcall.

Calling C for Lua can damage the memory structure when the new C function is added to LUA. When we write a library function for Lua (the LUA call function of C), there is only one standard error-handling method. When a C function detects an error, it should call the Lua_error,lua_error function to clean up all the things in Lua that need to be cleaned up, then jump back to the lua_pcall that initiated the execution and attach an error message. In the following blog post, there will be examples of this code.

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.