Notes on building lua development environment in VS2019 and interaction between C + + and lua

The following contents are taken from online public documents

1. Download the source code: http://www.lua.org/ftp/

2.1 compiling dll:

Add Lua in "C/C + +" > "preprocessor" - > "preprocessor definition"_ BUILD_ AS_ DLL: no lib

Do not add (lua.c and luac.c)

2.2 compile exe and add corresponding files

lua.c: Compiler

luac.c: Interpreter

 3. Test the generated libraries (x64,x86 and libraries should be consistent)

3.1 stack operation

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 
 4 //Note add extern "C",Otherwise, a link error occurs
 5 extern "C" {
 6 #include "lua.h"
 7 #include "lualib.h"
 8 #include "lauxlib.h"
 9 }
10 
11 #ifdef _DEBUG
12 #pragma comment(lib,"./Lua/Debug/Luad.lib")
13 #else
14 #pragma comment(lib,"./Lua/Release/Lua.lib")
15 #endif
16 
17 static void stackDump(lua_State* L)
18 {
19     int i = 0;
20     int top = lua_gettop(L);
21     for (i = 1; i <= top; i++)
22     {
23         int t = lua_type(L, i);
24         switch (t)
25         {
26         case LUA_TSTRING: /* strings */
27             printf("`%s'", lua_tostring(L, i));
28             break;
29         case LUA_TBOOLEAN: /* booleans */
30             printf(lua_toboolean(L, i) ? "true" : "false");
31             break;
32         case LUA_TNUMBER: /* numbers */
33             printf("%g", lua_tonumber(L, i));
34             break;
35         default: /* other values */
36             printf("%s", lua_typename(L, t));
37             break;
38         }
39         printf(" "); /* put a separator */
40     }
41     printf("\n"); /* end the listing */
42 }
43 
44 int main(int argc, char** argv)
45 {
46     lua_State* L = luaL_newstate();  // establish Lua virtual machine
47 
48     luaL_openlibs(L);                // open Lua State machine"L"All in Lua Standard library
49 
50     // Push value into virtual stack
51     lua_pushboolean(L, 1);           // true
52     lua_pushnumber(L, 10);           // 10
53     lua_pushnil(L);                  // nil
54     lua_pushstring(L, "hello");      // "hello"
55     stackDump(L);                    // true  10  nil  'hello'
56 
57     lua_pushvalue(L, -4);            // Index-4 Stack a copy of the value at
58     stackDump(L);                    // true  10  nil  'hello'  true
59 
60     lua_replace(L, 3);               // Move the top element of the stack to index 3 and overwrite the original element
61     stackDump(L);                    // true  10  true  'hello'
62 
63     lua_settop(L, 6);                // Set the top of the stack to index 6, and the extra new elements are assigned as"nil"
64     stackDump(L);                    // true  10  true  'hello'  nil  nil
65 
66     lua_remove(L, -3);               // Remove index-3 The element at which all elements are moved down
67     stackDump(L);                    // true  10  true  nil  nil
68 
69     lua_settop(L, -5);              // Set stack top to index-5 place
70     stackDump(L);                   // true
71 
72     lua_close(L);                   // close Lua State machine
73 
74     system("pause");//stay Linux Next compilation, please note this line
75 
76     return 0;
77 }

3.2 C calls Lua

 1 static int multi_math(lua_State* L, int x, int y)
 2 {
 3     int ret = 0;
 4     int add_ret = 0;
 5     int sub_ret = 0;
 6     int mul_ret = 0;
 7 
 8     //call lua_add
 9     lua_getglobal(L, "lua_add");//Put function lua_add Push into stack
10     stackDump(L);                //function
11     lua_pushnumber(L, x);        //function 2
12     lua_pushnumber(L, y);        //fucntion 2 1
13     stackDump(L);
14     lua_call(L, 2, 1);         //Indicates that there are 2 parameters, 1 return value, and function 2 1 Pop up the stack and push the return value into the stack
15 
16     stackDump(L);
17     add_ret = (int)lua_tonumber(L, -1);
18     stackDump(L);
19     printf("add_ret = %d\n", add_ret);
20     lua_pop(L, 1);                //Pop stack top
21     stackDump(L);
22 
23 #if 0
24     //call local lua_sub will cause running error 
25     lua_getglobal(L, "lua_sub");
26     lua_pushnumber(L, x);
27     lua_pushnumber(L, y);
28     lua_call(L, 2, 1);
29     sub_ret = (int)lua_tonumber(L, -1);
30     printf("sub_ret = %d\n", sub_ret);
31     lua_pop(L, 1);
32 #endif
33     //call lua_mul
34     lua_getglobal(L, "lua_mul");
35     lua_pushnumber(L, x);
36     lua_pushnumber(L, y);
37     lua_call(L, 2, 1);
38     mul_ret = (int)lua_tonumber(L, -1);
39     printf("mul_ret = %d\n", mul_ret);
40     lua_pop(L, 1);
41 
42     return ret;
43 }
44 int main(int argc, char** argv)
45 {
46     lua_State* L = luaL_newstate(); // establish Lua virtual machine
47     luaL_openlibs(L);               // open Lua State machine"L"All in Lua Standard library
48 
49     printf("call lua ....\n");
50     if (luaL_dofile(L, "main.lua"))//Load run main.lua
51     {
52         printf("call lua failed!\n");
53     }
54     if (multi_math(L, 2, 1))
55     {
56         printf("call multi_math failed!\n");
57     }
58 
59     lua_close(L); // close Lua State machine
60 
61     system("pause");
62 
63     return 0;
64 }

3.3 lua call C

Its interface must follow the form required by Lua, that is, typedef int (*lua_CFunction)(lua_State* L)

 1 //stay Lua Invoked C Register functions.
 2 static int add2(lua_State* L)
 3 {
 4     //Check whether the parameters in the stack are legal. 1 means Lua The first parameter when calling(From left to right),And so on.
 5     //If Lua The parameter passed by the code when calling is not number,This function will report an error and terminate the execution of the program.
 6     double op1 = luaL_checknumber(L, 1);
 7     double op2 = luaL_checknumber(L, 2);
 8     //Push the result of the function onto the stack. If there are multiple return values, you can push them into the stack multiple times here.
 9     lua_pushnumber(L, op1 + op2);
10     //The return value is used to prompt the C The number of return values of the function, that is, the number of return values pushed into the stack.
11     return 1;
12 }
13 //Another to be Lua Invoked C Register functions.
14 static int sub2(lua_State* L)
15 {
16     double op1 = luaL_checknumber(L, 1);
17     double op2 = luaL_checknumber(L, 2);
18     lua_pushnumber(L, op1 - op2);
19     return 1;
20 }
21 const char* testfunc = "print(add2(1.0,2.0)) print(sub2(20.1,19))";
22 
23 int main()
24 {
25     lua_State* L = luaL_newstate();
26     luaL_openlibs(L);
27     //Registers the specified function as Lua Global function variable, where the first string parameter is Lua code
28     //In call C The global function name used in the function. The second parameter is the actual value C Pointer to the function.
29     lua_register(L, "add2", add2);
30     lua_register(L, "sub2", sub2);
31     //After registering all C Function, you can Lua Use these registered in the code block of C Function.
32     if (luaL_dostring(L, testfunc))
33         printf("Failed to invoke.\n");
34     lua_close(L);
35     return 0;
36 
37 }

3.4 C function library becomes Lua's module (no direct excerpt for the time being).

Copy the code generation library file containing C function, such as so of Linux or DLL of Windows, to the current directory where Lua code is located, or Lua_ The directory pointed to by cpath environment variable so that Lua parser can locate them correctly. In my current Windows system, I copy it to "C: \ program files \ Lua \ 5.1 \ clips \", which contains all C libraries that Lua can call. See the following C language codes and key notes:


#include <stdio.h>
#include <string.h>
#include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>
//C function to be registered. The declaration form of this function has been given in the above example.
//It should be noted that this function must be exported in the form of C, so extern "C" is necessary.
//The function code is the same as the above example, which will not be repeated here.
extern "C" int add(lua_State* L) 
{
    double op1 = luaL_checknumber(L,1);
    double op2 = luaL_checknumber(L,2);
    lua_pushnumber(L,op1 + op2);
    return 1;
}
extern "C" int sub(lua_State* L)
{
    double op1 = luaL_checknumber(L,1);
    double op2 = luaL_checknumber(L,2);
    lua_pushnumber(L,op1 - op2);
    return 1;
}
//luaL_ The first field of the reg structure is a string, which is used to inform Lua of the name of the function during registration.
//The first field is the C function pointer.
//The two fields of the last element in the structure array are NULL, which is used to prompt Lua that the registration function has reached the end of the array.
static luaL_Reg mylibs[] = { 
    {"add", add},
    {"sub", sub},
    {NULL, NULL} 
};
//The unique entry function of the C library. Its function signature is equivalent to the above registered function. See the following description:
//1. We can simply understand this function as the factory function of the module.
//2. Its function name must be luaopen_xxx, where xxx represents the library name. Lua code require "xxx" needs to correspond to it.
//3. In lual_ In the call of register, the first string parameter is the module name "xxx", and the second parameter is the array of functions to be registered.
//4. It should be emphasized that all codes that need to use "xxx", whether C or Lua, must be consistent. This is Lua's agreement,
//Otherwise, it cannot be called.
extern "C" __declspec(dllexport)
int luaopen_mytestlib(lua_State* L) 
{
    const char* libName = "mytestlib";
    luaL_register(L,libName,mylibs);
    return 1;

See Lua code below:

require "mytestlib" -- specify the package name
-- when calling, it must be package function
 print(mytestlib.add(1.0,2.0))
 print(mytestlib.sub(20.1,19))

Keywords: lua

Added by DarkHavn on Thu, 03 Feb 2022 03:29:26 +0200