Cross-C + + and Lua for intermodulation

Source: Internet
Author: User
Tags add numbers lua stack trace

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

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.