Today, we will continue to talk about the development of LuatOS. In the last issue, we briefly talked about it How to migrate LuatOS , I believe many friends have seen it. So today, I'll start talking about some tutorials of C and Lua calls.
See the following links for information about LuatOS and the official definition of Lua language:
LuatOS warehouse:
https://gitee.com/openLuat/LuatOS
Lua 5.3 Chinese Reference Manual:
https://www.runoob.com/manual/lua53doc/contents.html
Chat about the call of C and Lua
LuatOS custom C library can realize user-defined functions, such as some high delay requirements. It will be more convenient and fast to use through C:
Lua uses a virtual stack to exchange values with C, that is, the data interaction between C and Lua is carried out on the stack.
Basic concept and principle of stack
As a data structure, stack is a special linear table that can only be inserted and deleted at one end.
It stores data according to the principle of first in and last out. The first entered data is pressed into the bottom of the stack, and the last data is at the top of the stack. When you need to read data, pop up data from the top of the stack (the last data is read out first).
Entering the stack is to put a new element on the top of the stack, and leaving the stack is to take an element out of the top of the stack. The element at the top of the stack is always the last to enter the stack. When it needs to be out of the stack, it is first taken out of the stack.
If you haven't touched the stack, think of it as a big bag that comes in first and then comes out. All you have to do is put and take things in it.
Whenever Lua calls C, the called function gets a new stack, which is independent of the stack of C function itself and the previous Lua stack. It contains all the parameters passed by Lua to the C function, and the C function puts the result to be returned on this stack to return to the caller.
Therefore, the call of C and Lua is to operate on the stack.
Introduction to common functions
When writing functions, first use lua_State: environment table, registry, run stack, context of virtual machine and other data in Lua virtual machine.
Common functions also involve judgment function, check function, fetch function, return function, etc., as shown below:
Common judgment function
lua_isboolean : lua_isboolean (lua_State *L, int index); Returns 1 when the value of the given index is a Boolean quantity, otherwise returns 0. lua_isinteger : lua_isinteger (lua_State *L, int index); Returns 1 when the value of the given index is an integer, otherwise returns 0. lua_isnil : lua_isnil (lua_State *L, int index); When the value of a given index is nil Returns 1, otherwise returns 0. lua_isnumber : lua_isnumber (lua_State *L, int index); Returns 1 when the value of a given index is a number or a string that can be converted to a number, otherwise returns 0. lua_isstring : lua_isstring (lua_State *L, int index); When the value of a given index is a string or a number( Numbers can always be converted to strings)Returns 1, otherwise returns 0.
Common check function
luaL_checkinteger : luaL_checkinteger (lua_State *L, int arg); Check the second part of the function arg Whether a parameter is an integer (or can be converted to an integer) and lua_Integer Type returns this integer value. luaL_checknumber : luaL_checknumber (lua_State *L, int arg); Check the second part of the function arg Whether a parameter is a number and returns this number. luaL_checkstring : luaL_checkstring (lua_State *L, int arg); Check the second part of the function arg Whether the first parameter is a string and returns the string. luaL_checklstring : luaL_checklstring (lua_State *L, int arg, size_t *l); Check the second part of the function arg Whether a parameter is a string and returns the string; If l Not for NULL , Fill in the length of the string *l. The string can be any binary data, including zero characters.
Common extraction function
luaL_optinteger : luaL_optinteger (lua_State *L , int arg , lua_Integer d); If the second part of the function arg A parameter is an integer (or can be converted to an integer), which is returned. If the parameter does not exist or nil, return d. In other cases, an error is thrown. luaL_optnumber : luaL_optnumber (lua_State *L, int arg, lua_Number d); If the second part of the function arg A parameter is a number that is returned. If the parameter does not exist or nil, return d. In other cases, an error is thrown. luaL_optstring : luaL_optstring (lua_State *L, int arg, const char *d); If the second part of the function arg The first parameter is a string that is returned. If the parameter does not exist nil, return d. In other cases, an error is thrown. luaL_optlstring : luaL_optlstring (lua_State *L , int arg , const char *d , size_t *l); If the second part of the function arg The first parameter is a string that is returned. If the parameter does not exist or nil, return d. In other cases, an error is thrown. if l Not for NULL, Fill in the length of the result *l . The string can be any binary data, including zero characters.
Common return function
lua_pushboolean : void lua_pushboolean (lua_State *L, int b); hold b As a Boolean stack. lua_pushinteger: lua_pushinteger (lua_State *L, lua_Integer n); Set the value to n Integer stack. lua_pushnumber : lua_pushnumber (lua_State *L, lua_Number n); Set a value to n Floating point number stack. lua_pushstring : lua_pushstring (lua_State *L, const char *s); Place pointer s The zero terminated string pointed to is stacked. If s by NULL,take nil Stack and return NULL. lua_pushlstring : lua_pushlstring (lua_State *L, const char *s, size_t len); Put the pointer s The pointing length is len String stack. The string can be any binary data, including zero characters.
be careful:
The difference between xxxlstring and xxxstring, the former is necessary to transmit binary data!!!
First function
To create a custom module framework:
Find the luat / moldes folder in the LuatOS source code directory and create a new one named luat_lib_xxx.c) documents;
First introduce "luat_base.h" into the C file. This header file contains the functions we need to use.
To create a custom function:
static int l\_jiaFa(lua\_State \*L) //The function name is generally written as l\_xxx , In this way, you can intuitively know that this is a and lua Interactive function { int a = luaL\_checkinteger(L, 1); //Take out the first value entered (type int) int b = luaL\_optinteger(L, 2, 0); //Take out the second value entered (type int) lua\_pushinteger(L, a + b); //Returns the sum of ab return 1; //Returns a value }
Analyze:
Function input (lua_State *L), as mentioned earlier, C and Lua are called in the stack;
The value of a is through luaL_checkinteger(L, 1); Obtained. This is a check function. When the first value entered is of type int, the function will return the value. Here, it is assigned to a.
The value of b is through luaL_optinteger(L, 2, 0); All you get is a fetching function. The fetching object is the second value input by lua function. If the second value is not of type int, it will return 0.
lua_pushinteger(L, a + b); Is the value returned to the Lua function (type int)
Last return 1; There is only one return value representing this function.
Register function:
#include "rotable.h" static const rotable\_Reg exa\[\] = //exa \ [\] is the name of your custom library { {"jiaFa", l\_jiaFa, 0}, //The first is the name of the function lua wants to call, The second is corresponding c Function, The third is lua\_Integer Value, usually written as 0 {NULL, NULL, 0}}; //There should be this line at the end, which means there are no other functions LUAMOD\_API int luaopen\_exa(lua\_State \*L) //Register a LUAMOD\_API, and then write luat\_base.h { luat\_newlib(L, exa); //Create a new table and register the functions in list L return 1; }
The focus here is rotable_Reg:
typedef struct rotable\_Reg { char const\* name; lua\_CFunction func; lua\_Integer value; } rotable\_Reg;
You need to end with null in this structure.
After writing the above paragraph, in luat_base.h plus LUAMOD_API int luaopen_exa(lua_State *L);
Enable custom module
Open the base file corresponding to the chip / module. For example, the base file of air302 is:
https://gitee.com/openLuat/LuatOS/blob/master/bsp/air302/src/luat_air302_base.c
according to Previous migration tutorial , we add {"exa", luaopen_exa} in loadedlibs [] to enable the module.
Compile new firmware
I won't elaborate here. There are compilation instructions in the LuatOS warehouse. I have also done compilation tutorials for air302 before. See the following for details:
https://doc.openluat.com/article/2047
Write Lua script
\-- LuaTools need PROJECT and VERSION These two messages PROJECT = "exademo" VERSION = "1.0.0" \-- sys The library is standard \_G.sys = require("sys") local function exatext() log.info("jiafa", exa.jiaFa(2,10)) end sys.timerLoopStart(exatext, 1000) \-- User code ended--------------------------------- \-- It always ends with this sentence sys.run() \-- sys.run()Don't add any statements after that!!!!!
Advanced function
When the previous steps are completed and ensure correct operation, then look down to the advanced part.
Return string
static int l\_reString(lua\_State \*L) { if (!lua\_isnumber(L, 1)) //If the input is a string (either number or string naturally) { const char \*c = luaL\_optstring(L, 1, ""); lua\_pushstring(L, c); //If the first input value is string, return directly return 1; } else { lua\_pushstring(L,"nostring"); //This means that the first value entered is not a string and returns nostring return 1; } }
This part has more judgment functions than the basic part. It's not difficult to understand it according to the notes.
Multiple input multiple return
static int l\_reMore(lua\_State \*L) { if (lua\_isinteger(L, 1)) //Determine whether the first value entered is int { lua\_pushboolean(L, 1); //Return true const char \*st = luaL\_optstring(L, 2, "nostring"); lua\_pushstring(L, st); //Return string return 2; } else { lua\_pushboolean(L, 0); //Return to flash return 1; } }
Here's the explanation while looking at the code:
1) The function first determines the first value type of lua input. If it is int type, it returns the first bool type value;
2) Now that you have determined that the first value is of type int, take out the second value entered by lua, assign it to st if it is string, and assign "nostring" to st if it is nil;
3) Return st and use the function lua_pushstring(L, st);
4) Analyze the definition of return value - we can see that in the braces where if is true, we first return the value of bool type, and then return the value of string type. A total of two values are returned, so the value of return is written as 2; In the braces of else, we only return a value of bool type, so the value of return is 1.
Shanghai Hezhou communication module - Hezhou Luat makes the interconnection of all things easier