1, calling a function in C + + code in a LUA script
When you define a function in C + +, you must use lua_state as the argument, and int as the return value to be called by Lua.
/*
typedef int (*lua_cfunction) (lua_state*l);
The type of the C function.
For proper communication with Lua, the C function must use the following protocol that defines the parameters and the method of passing the return value: The C function takes the parameters through the stack in Lua, and the arguments are in the forward sequence (the first argument is first entered into the stack). Therefore, when the function starts, Lua_gettop (L) can return the number of arguments received by the function. The first parameter, if any, is at index 1, and the last parameter is at index Lua_gettop (L). When you need to return values to Lua, the C function simply presses them on the stack (the first return value is pressed first) and returns the number of these return values. Below these return values, the contents on the stack will be discarded by Lua. As with LUA functions, calling C functions from Lua can also have a lot of return values.
*/
The function in the following example will receive several numeric parameters and return their averages with the and:
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif/* __cplusplus */
#include <lua.h>/LUA is written in pure C language
#include <lualib.h>
#include <lauxlib.h>
#ifdef __cplusplus
}
#endif/* __cplusplus */
int C_average (lua_state* L)
{
int n = lua_gettop (L); /* Returns the index of the top element of the stack. Because the index is numbered starting at 1 (1 for the bottom of the stack, 1 for the top of the stack), the result is equal to the number of elements on the stack (returning 0 means that the stack is empty). The number of elements in this stack is the number of parameters passed in.
Double sum = 0;
int i;
for (i = 1; I <= n; i++)
{
if (!lua_isnumber (L, i))
{
Lua_pushstring (L, "incorrect argument to ' average '"); Press the error message into the stack
Lua_error (L); Throw top of Stack error
/*
int Lua_error (lua_state *l);
Produces a Lua error. The error message (which can actually be any type of Lua value) must be placed on top of the stack. This function will do a long jump and it will not return.
*/
}
Sum + = Lua_tonumber (L, i); Lua_tonumber converts the value of the specified index in the stack to the value of a numeric type, noting that the value is not popped from the stack
}
Double avg = sum/n;
Lua_pushnumber (L, avg); The AVG is pressed into the stack, and the 1th return value is avg
Lua_pushnumber (L, sum); The sum is pressed into the stack, and the 2nd return value is sum
return 2; /* Return the number of results, the function has 2 return values, that is, the above stack of AVG and sum */
}
int main (int argc, char* argv[])
{
lua_state* L = Lual_newstate (); Create a new stand-alone state machine
/* Register our function, tell Lua script to call the average function (the variable name in LUA) corresponds to a C function called C_average */
Lua_register (L, "average", c_average);
/*
void Lua_register (Lua_state *l,
const Char *name,
Lua_cfunction f);
Set the C function f to the global variable name. It is defined by a macro:
#define Lua_register (l,n,f) \
(Lua_pushcfunction (L, F), Lua_setglobal (l, N))
*/
/* Run the script */
Lual_dofile (L, "E1.lua"); Load script, executable statement in script will be executed
/* Loads a file as a Lua chunk and then calls a function in protected mode equivalent to (Lual_loadfile (l,filename) | | lua_pcall (L, 0, Lua_multret, 0)) */
Lua_getglobal (L, "avg"); The value of the global variable avg is in the stack, equivalent to Lua_getfield (L,lua_globalsindex, "name")
printf ("Avg is:%d\n", Lua_tointeger (L,-1)); Read the int value at the top of the stack, and note that this element is not popped from the stack
Lua_pop (L, 1); An element that pops up the top of the stack
Lua_getglobal (L, "sum"); Put the value of the global variable sum into the stack
printf ("Sum is:%d\n", Lua_tointeger (L,-1));
Lua_pop (L, 1); An element that pops up the top of the stack
/* Cleanup Lua */
Lua_close (L);
return 0;
}
/*
--E1.lua
AVG, sum = average (10, 20, 30, 40, 50)
Print ("The average is", avg)
Print ("The sum is", sum)
*/
/*
Output:
The average is 30
The sum is 150
Avg is:30
Sum is:150
*/
2, invoking a function in a LUA script in a C + + code
Passing parameters to a function in a LUA script through a stack in C + + code, the parameters are entered in the stack in the positive order, and the return value is pressed into the stack by LUA for C + + access. (After the function call succeeds, both the name and the parameter are out of the stack, and the return value is in the stack)
Example:
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif/* __cplusplus */
#include <lua.h>/LUA is written in pure C language
#include <lualib.h>
#include <lauxlib.h>
#ifdef __cplusplus
}
#endif/* __cplusplus */
lua_state* L = NULL;
int luaadd (int x, int y)
{
int sum;
/* The function name in the Name,lua script */
Lua_getglobal (L, "add"); Lua function name into the stack
int savedtop = Lua_gettop (L); Save the number of elements in the stack, after which you want to restore
/* The first argument */
Lua_pushnumber (L, x); parameter x into the stack
/* The second argument */
Lua_pushnumber (L, y); Parameter y into the stack
At this time there are 3 values in the stack, the top of the stack is the parameter y, the bottom is the function name add
/* Call the function with 2 arguments, return 1 result */
Lua_call (L, 2, 1);
/*
void Lua_call (lua_state *l, int nargs, int nresults);
Call a function.
To invoke a function, observe the following protocol: first, the function to be called should be pressed into the stack, and then the arguments that need to be passed to the function are pressed in the positive sequence, which means that the first parameter is stacked first. Finally call Lua_call; Nargs is the number of arguments you press into the stack. When the function call is complete, all arguments and the function itself will be stacked. The return value of the function is then pressed into the stack. The number of return values will be adjusted to Nresults unless Nresults is set to Lua_multret. In this case, all the return values are pressed into the stack. Lua guarantees that the return value is placed in the stack space. The return value of the function will be stacked on a positive sequence (the first return value is stacked first), so the last return value will be placed at the top of the stack after the call ends.
Lua_pcall (lua_state *l, int nargs, int nresults, int errfunc);
Invokes a function in protected mode.
The meaning of Nargs and Nresults is the same as in Lua_call. If no error occurs during the call, the behavior of Lua_pcall is exactly the same as the Lua_call. However, if an error occurs, Lua_pcall captures it and then presses the single value (error message) onto the stack and returns the error code. Like Lua_call, Lua_pcall always removes the function itself and its arguments from the stack.
If Errfunc is 0, the error message returned at the top of the stack is exactly the same as the original error message. Otherwise, the errfunc is treated as an index on the stack of the error handling function. (In the current implementation, this index cannot be a pseudo-index.) When a run-time error occurs, the function is called and the parameter is the error message. The return value of the error-handling function is returned on the stack as an error message by Lua_pcall.
In a typical usage, the error handling function is used to add more debug information to the error message, such as stack trace information (stack traceback). This information is not collected after Lua_pcall returns because the stack has been expanded (unwound).
The Lua_pcall function returns 0 when the call succeeds, or returns one of the following (defined in LUA.H) error codes:
Lua_errrun: Run-time error.
LUA_ERRMEM: Memory allocation error. For this kind of mistake, Lua cannot invoke the error handling function.
Lua_errerr: An error occurred while running the error handling function.
*/
Because add has only one return value, there are only 1 values in the stack (if there are multiple return values, it is also in the positive sequence)
/* Get the result */
sum = (int) lua_tonumber (L,-1); -1 is the top of the stack
Lua_pop (L, 1); return value out of stack
/* Remove the value of the variable z in the script */
Lua_getglobal (L, "Z"); Value of the variable z into the stack
int z = (int) lua_tonumber (L,-1);
printf ("z =%d\n", z);
Lua_pop (L, 1); Variable z out of stack
Lua_pushnumber (L, 4); 4 into the stack
Lua_setglobal (L, "R");
/*
void Lua_setglobal (lua_state *l, const char *name);
POPs a value from the stack and sets it to the global variable name. It is defined by a macro:
#define LUA_SETGLOBAL (l,s) Lua_setfield (L, Lua_globalsindex, s)
*/
Lua_getglobal (L, "R"); Value of variable r into the stack
int r = (int) lua_tonumber (L,-1);
printf ("R =%d\n", r);
Lua_pop (L, 1); Variable r out of the stack
Lua_settop (L, savedtop); Restore the original stack before the function exits
return sum;
}
int main (int argc, char* argv[])
{
L= lual_newstate (); Create a LUA runtime environment
/* Load the script, load the scripts, and prepare for the variables to be read later.
Lual_dofile (L, "E2.lua");
/* Call the Add function */
int sum = Luaadd (10, 15);
/* Print the result */
printf ("The sum is%d\n", sum);
/* Cleanup Lua */
Lua_close (L);
return 0;
}
/*
--E2.lua
--Add numbers
function add (x, y)
return x + y
End
z = 6
*/
/*
Output:
z = 6
R = 4
The sum is 25
*/
3, General examples
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif/* __cplusplus */
#include <lua.h>/LUA is written in pure C language
#include <lualib.h>
#include <lauxlib.h>
#ifdef __cplusplus
}
#endif/* __cplusplus */
#define ERR_EXIT (Num,fmt,args ...) \
Do{printf ("[%s:%d]" FMT "\ n", __file__,__line__,# #args); exit (num);} while (0)
#define Err_return (Num,fmt,args ...) \
Do{printf ("[%s:%d]" FMT "\ n", __file__,__line__,# #args); return (num);} while (0)
c function definition called in Lua, implementation of addition
int C_sum (lua_state* L)
{
int a = Lua_tointeger (L, 1);
int b = Lua_tointeger (L, 2);
Lua_pushinteger (L, A + b);
return 1;
}
int main (int argc, char* argv[])
{
lua_state* L = Lual_newstate (); Create a LUA runtime environment
if (L = = NULL)
Err_return ( -1, "Lual_newstat () failed");
int ret = 0;
ret = Lual_loadfile (L, "E3.lua"); Loads a file as a luachunk. The underlying invocation of lua_load is the ability to load a Lua chunk. If there is no error, Lua_load puts a compiled chunk into the stack as a LUA function. Otherwise, the error message is pressed in.
if (ret! = 0)
Err_return ( -1, "Lual_loadfile failed");
ret = Lua_pcall (L, 0, 0, 0); Invokes a function in protected mode. The file that was just loaded
if (ret! = 0)
Err_return ( -1, "Lua_pcall failed:%s", Lua_tostring (L,-1));
Lua_getglobal (L, "width"); Put the value of the global variable width into the stack
Lua_getglobal (L, "height");//Put the value of the global variable height into the stack
printf ("Height:%ld, Width:%ld\n", (long) Lua_tointeger (l,-1), (long) Lua_tointeger (L,-2));
Lua_pop (L, 1); POPs a value from the stack, starting at the top of the stack
int a = 11;
int B = 12;
Lua_getglobal (L, "mySum1"); MYSUM1 the global variable into the stack, note that mySum1 here is a function
Lua_pushinteger (L, a); 1th integer parameter in the stack, left to right order
Lua_pushinteger (L, b); 2nd integer parameter in the stack, left to right order
ret = Lua_pcall (L, 2, 1, 0); Call function, 2 parameters, 1 return values. After the call succeeds, both the function and the argument play, returning the value into the stack. If there are multiple return values, the first return value is first in the stack
if (ret! = 0)
Err_return ( -1, "Lua_pcall failed:%s", Lua_tostring (L,-1));//The Stack top holds failed after calling function failed reason string
printf ("Sum:%d +%d =%ld\n", A, B, (long) Lua_tointeger (l,-1)); Sum has only one return value, and the return value of the stack top holds the function after the call succeeds
Lua_pop (L, 1);
const char str1[] = "Hello";
const char str2[] = "World";
Lua_getglobal (L, "Mystrcat"); Call a function in Lua Mystrcat
Lua_pushstring (L, str1);
Lua_pushstring (L, str2);
ret = Lua_pcall (L, 2, 1, 0);
if (ret! = 0)
Err_return ( -1, "Lua_pcall failed:%s", Lua_tostring (L,-1));
printf ("Mystrcat:%s%s =%s\n", str1, str2, lua_tostring (l,-1));
Lua_pop (L, 1);
Lua_pushcfunction (L, c_sum); Press a C function onto the stack
Lua_setglobal (L, "mySum2");
/*
void Lua_setglobal (lua_state *l, const char *name);
POPs a value from the stack and sets it to the global variable name. It is defined by a macro:
#define LUA_SETGLOBAL (l,s) Lua_setfield (L, Lua_globalsindex, s)
*/
The above two sentences can be used Lua_register (L, "mySum2", c_sum);
/* Register our function, tell Lua script to call the average function (also a variable name) actually corresponds to a C code function called C_averaged */
Call the MYSUM2 function in Lua, which calls the C_sum function to implement the addition
Lua_getglobal (L, "mySum2");
Lua_pushinteger (L, a);
Lua_pushinteger (L, b);
ret = Lua_pcall (L, 2, 1, 0);
if (ret! = 0)
Err_return ( -1, "Lua_pcall failed:%s", Lua_tostring (L,-1));
printf ("MySum:%d +%d =%ld\n", A, B, (long) Lua_tointeger (l,-1));
Lua_pop (L, 1);
Lua_close (L); Releasing the LUA runtime environment
return 0;
}
/*
--E3.lua
--Variable definition
width = 1
Height = 2
--LUA function definition, implementing addition
function MySum1 (A, B)
Return a + b
End
--LUA function definition, implementation of string addition
function Mystrcat (A, B)
Return a. "_" .. B
End
--Lua function definition, by invoking the Csum function in C code to implement the addition
function MySum (A, B)
Return Csum (A, B)
End
*/
/*
Output:
Height:2, Width:1
Sum:11 + 12 = 23
Mystrcat:hello World = Hello_world
Mysum:11 + 12 = 23
*/
Cross-C + + and LUA tuning