Date: 2014.8.7
Part IV the C API
27 Calling C from Lua
Here, Lua calls the C function, which does not mean that Lua can call any C function. Like calling the Lua function by C, the following rules must be followed: Passing parameters to obtain the result. In addition, to call the C function, Lua needs to register the function first, that is, to pass the address of the function to Lua.
When Lua calls the C function, it also uses the stack to pass Parameters and return results. Function C obtains parameters from the stack and pushes the result to the stack.
An important concept here is that the stack is not a global structure; each function has its own local stack. When Lua calls the C function, the first parameter is always the value of Index 1 in the stack. Even if a C function calls the Lua code and then Lua calls a C function, each call can only access each selfish stack, the first parameter is the one with index 1 in the stack.
27.1 c Functions
As an example in the book, how to implement a simple function that returns a given sin value:
E. g. static int l_sin (lua_state * l) {double D = lua_tonumber (L, 1);/* Get a parameter */lua_pushnumber (L, sin (d )); /* Push the result into */return 1;/* Number of returned results */}
Any function registered with Lua has the same prototype, which is defined as lua_cfuntion in the header file Lua. h:
typedef int (*lua_CFuntion) (lua_State *L)
From the perspective of C, a C function uses a Lua state as its unique parameter and returns an integer that represents the number of function return values. From this point of view, the function does not need to clear the stack before pushing the result. After the function returns, Lua automatically stores the result and clears the entire stack.
Before using this function in Lua, We need to register this function first. We use lua_pushcfunction to implement this function: Get a pointer from the C function, and create a function-type variable to represent this function in Lua. Once this function is registered, the C function is consistent with the function in Lua:
E. g. lua_pushcfunction (L, l_sin); lua_setglobal (L, "mysin");/* create a global variable mysin in Lua and assign the C function to mysin */
After that, you can use the mysin function in Lua.
We need to check the parameter type to make the function more standard. In this case, the auxiliary function lual_checknumber will do this. This function checks whether the given parameter is a number. If an error occurs, the function will throw an error message, otherwise, the number of checks will be returned. EXAMPLE After modification:
E. g. static int l_sin (lua_state * l) {double D = lual_checknumber (L, 1)/* Check parameter */lua_pushnumber (L, sin (d); return 1 ;}
If the passed parameter is not numeric, an error message is displayed:
Bad argument #1 to 'myoussin '(number expected, got string)
In this case, the error message shows how to obtain the passed parameter, function name, parameter type required by the function, and actual parameter type. note this.
27.2 continuations
Through lua_pcall and lua_call, a C function called by Lua can call back another Lua function. Several Functions in the standard library support this operation: Table. Sort can call an ordering function; string. gusb can call an alternative function; pcall and xpcall can call a function in safe mode. Here I will mention that the main program of Lua is called from C (the Host Program), and there is a queue here: C (the host) calls Lua (SCRIPT ), the Lua script calls C (Standard Library), and C (standard library) calls Lua (callback ).
Generally, there is no problem for Lua to process this queue, but it is a bit difficult in the coprocessor.
Each synergy program in Lua has its own stack to store information about the unexecuted calling of the collaboration program. In particular, this stack will store the return address, parameters, and some local variables for each access. When calling the Lua function, the interpreter uses the appropriate data structure to implement this stack (soft stack). When calling the C function, the interpreter must use the C stack. After all, the return address and local variables of the C function are stored in the C stack.
The interpreter can easily have multiple Sofe stacks, but the runtime of ansi c can only have one internal stack. This means that Lua cannot delay the execution of C functions: assume that there is a C function accessed during the process from the resume status to other statuses, Lua cannot store the status of the C function for the next resume of resume. Here is an example:
e.g.co = coroutine.wrap(function ( a ) return pcall(function ( x ) coroutine.yield(x[1]) return x[3] end,a)end)print(co({10,3,-8,15}))
This example is executed in sublime. It is mentioned in the book that there is a problem and you need to pay attention to it. The book explains this example: pcall is a C function, so Lua cannot delay the execution of this function, in ansi c, there is no way to delay the execution of a C function and restore it at a certain point in time.
In lua5.2, continuations was used to correct this problem (now I am using version 5.2 and may have fixed it now). lua5.2 uses long jumps to implement yields, the same method is used to handle errors. A long jump only throws information about the C function in the C stack, so this function can be restored.
27.3 C modules
The module in Lua is to define multiple functions and store them in a proper place. It is generally stored in a table. A c Module is similar to this. Of course, apart from defining C functions, you must also define a special function. Its function is similar to main chunk in Lua. This function is used to register all the c Functions in the module and store these functions in a proper place, which is generally table. Like the main chunk of Lua, this function should also initialize anything required by the module.
Lua listens to the C function through the registration process of the C function. Once a C function is stored in Lua, Lua can call this function immediately through its address (obtained when registering the function. This also indicates that Lua does not rely on the function name, package location, and so on to call the C function. In particular, a C Module has a public function that is used to open this module, while other functions in the module can be private and declared as static.
When you want to use the C function to expand Lua, encapsulating the extension code into the C module is a good choice, even if there is only one function: Because eventually you will need other functions. As usual, the Helper function library provides a helper function: lual_newlib obtains a list of C functions based on their respective function names, registers all functions, and stores them in a new table. Here is an example: if we want to create a library with a function Rochelle Dir, we need to define this library function first:
e.g.static int l_dir(lua_State *L){ /*code*/}
The next step is to declare a Data Structure to store all the functions that need to be added to the database using the names of their respective functions. The data structure type is lual_reg. The data structure of the array has two fields: A string represents the name of a function and a function pointer.
e.g.static const struct luaL_Reg mylib[] = { {"dir",l_dir), {NULL,NULL}};
It must end with {null, null} and is used as the end symbol. Finally, declare a main function and use lual_newlib:
e.g.int luaopen_mylib(lua_State *L){ luaL_newlib(L,mylib); return 1;}
After the library is created, the Library is linked to the compiler. The most convenient way is to use the dynamic link feature (create mylib. dll in windows, create mylib. So in Linux) and then add it to the C path. After these steps, you can load the library from Lua and implement it using require:
e.g.local mylib = require "mylib"
The above step links the dynamic link library mylib to Lua, finds the luaopen_mylib function, registers the function with a C function, and then calls the function to open the module.
The dynamic linker requires that you know the name of the luaopen_mylib function to find the function. Generally, the name of the luaopen _ + module is used for searching. Therefore, if the module name is mylib, the function name must be luaopen_mylib.
If the compiler does not support dynamic links, you need to recompile Lua to add it to your new library. You also need to tell the compiler that you need to open the newly added library. Generally, the new library is added to the open list of the standard library, in linit. c, so that lual_openlibs can open these libraries.
Programming in Lua 3 Reading Notes (23)