本人测试环境: centos7 openresty
main.cpp
#include#include using namespace std; int simple_test(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into simple_test" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; // 获取lua脚本传过来的参数 const char *name = lua_tostring(L, -2); // size_t len; // const char *name = lua_tolstring(L, -2, &len); lua_Integer age = lua_tointeger(L, -1); lua_pop(L, 2); cout << "name:" << name << " age:" << age << endl; // lua脚本调用函数的返回值 lua_pushinteger(L, 99); cout << "当前栈上数量 = " << lua_gettop(L) << endl; return 1; } int array_test(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into array_test" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; luaL_checktype(L, 1, LUA_TTABLE); // 方法 1 { // 因为lua_next 的第1步会先从栈顶弹出一个key, 如果没值会出错,所以这里压个nil,让其不出错 lua_pushnil(L); // lua_next(L, 1) => 1 是 table在栈中的位置 // 1. 先从栈顶弹出一个key (因为是数组,所以这个key就是序号了) // 2. 从栈指定位置的table中取一对 key-value, 先将key入栈,再将value入栈 // 3. 如果第2步成功则返回非0值, 否则返回0, 且不向栈中压入任何值 while (lua_next(L, 1) != 0) { cout << "key: " << lua_tonumber(L, -2) << " value: " << lua_tostring(L, -1) << endl; // lua_next会把key弹掉, 所以这里只要弹掉value即可恢复栈 lua_pop(L, 1); } lua_pop(L, 1); // 弹出table } // 方法 2 { // size_t n = lua_objlen(L, -1); // for (int i = 1; i <= n; ++i) { // // 索引号压栈 // lua_pushnumber(L, i); // // // 1. 上一步的num出栈(pop number) , 这里 num = i // // 2. 通过这个num,获取索引号对应的值table[num] // // 3. 把这个值table[num] 压栈 (push table[num] ) // lua_gettable(L, 1); // // // 获取这个值table[num] // cout << lua_tostring(L, -1) << endl; // // // 出栈, 1 是出栈的数量 // lua_pop(L, 1); // } // lua_pop(L, 1); // 弹出table } cout << "当前栈上数量 = " << lua_gettop(L) << endl; return 0; } int map_test(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into map_test" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; luaL_checktype(L, 1, LUA_TTABLE); // 方法 1 { // 因为lua_next 的第1步会先从栈顶弹出一个key, 如果没值会出错,所以这里压个nil,让其不出错 lua_pushnil(L); // lua_next(L, 1) => 1 是 table在栈中的位置 // 1. 先从栈顶弹出一个key // 2. 从栈指定位置的table中取一对 key-value, 先将key入栈,再将value入栈 // 3. 如果第2步成功则返回非0值, 否则返回0, 且不向栈中压入任何值 while (lua_next(L, 1) != 0) { cout << "key: " << lua_tostring(L, -2) << " value: " << lua_tostring(L, -1) << endl; // lua_next会把key弹掉, 所以这里只要弹掉value即可恢复栈 lua_pop(L, 1); } lua_pop(L, 1); // 弹出table } // 方法 2 (根据key 获取 value) // { // lua_getfield(L, 1, "a"); // 获取到 table["a"] 的值, 压入栈顶 // cout << "a => " << lua_tostring(L, -1) << endl; // // lua_getfield(L, 1, "b"); // cout << "b => " << lua_tostring(L, -1) << endl; // // lua_getfield(L, 1, "c"); // cout << "c => " << lua_tostring(L, -1) << endl; // // lua_getfield(L, 1, "d"); // cout << "d => " << lua_tostring(L, -1) << endl; // // lua_pop(L, 5); // 全部弹出 // } cout << "当前栈上数量 = " << lua_gettop(L) << endl; return 0; } int checkType_test(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into checkType_test" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; // luaL_checktype , 一旦类型不符合, 代码不会继续执行 luaL_checktype(L, -1, LUA_TBOOLEAN); cout << "第1个参数类型检查通过" << endl; // lua_type , 就算类型不符合, 代码也会继续执行 int nType = lua_type(L, -2); if (nType != LUA_TNUMBER) { cout << "第2个参数类型不符合" << endl; // luaL_argerror(L, -2, "参数类型不符合"); } lua_pop(L, 2); cout << "当前栈上数量 = " << lua_gettop(L) << endl; return 0; } int ret_test(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into ret_test" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; lua_pushstring(L, "张三"); lua_pushnumber(L, 12); cout << "当前栈上数量 = " << lua_gettop(L) << endl; return 2; } int ret_table_test(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into ret_table_test" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; // 创建表,压栈 lua_newtable(L); // 一对key value 入栈 // 压入key lua_pushstring(L, "name"); // 压入value lua_pushstring(L, "张三"); // 此时,表在栈底 // 弹出 key value 设置到表. 此时,表在栈顶了 lua_settable(L, 1); //------------------------------- // 一对key value 入栈 // 压入key lua_pushstring(L, "age"); // 压入value lua_pushinteger(L, 22); // 此时,表在栈底 // 弹出 key value 设置到表. 此时,表在栈顶了 lua_settable(L, 1); cout << "当前栈上数量 = " << lua_gettop(L) << endl; return 1; } int getLuaVar_test(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into getLuaVar_test" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; lua_getglobal(L, "g_var1"); lua_Number num = lua_tonumber(L, -1); cout << "g_var1 = " << num << endl; lua_pop(L, 1); cout << "当前栈上数量 = " << lua_gettop(L) << endl; return 0; } int set2LuaVar_test(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into set2LuaVar_test" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; lua_pushstring(L, "赵六"); // 将栈顶位置设置为全局变量,并出栈 lua_setglobal(L, "g_name"); cout << "当前栈上数量 = " << lua_gettop(L) << endl; return 0; } int getLuaVar_table_test(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into getLuaVar_table_test" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; // 一层map { cout << "----------- 一层map ----------" << endl; lua_getglobal(L, "g_t1"); { lua_getfield(L, -1, "name"); // name的值入栈 const char *name = lua_tostring(L, -1); cout << "name = " << name << endl; lua_pop(L, 1); // 弹掉 name lua_getfield(L, -1, "age"); // age的值入栈 lua_Number age = lua_tonumber(L, -1); cout << "age = " << age << endl; lua_pop(L, 1); // 弹掉 age } lua_pop(L, 1); // 弹掉 g_t1 cout << "当前栈上数量 = " << lua_gettop(L) << endl; } // 嵌套的map { cout << "----------- 嵌套的map ---------" << endl; lua_getglobal(L, "g_t2"); { // 因为lua_next 的第1步会先从栈顶弹出一个key, 如果没值会出错,所以这里压个nil,让其不出错 lua_pushnil(L); // lua_next(L, 1) => 1 是 table在栈中的位置 // 1. 先从栈顶弹出一个key // 2. 从栈指定位置的table中取一对 key-value, 先将key入栈,再将value入栈 // 3. 如果第2步成功则返回非0值, 否则返回0, 且不向栈中压入任何值 while (lua_next(L, 1) != 0) { lua_Number key = lua_tonumber(L, -2); cout << "key: " << key << endl; // 取value的值, 这里的value就是子table, 在栈顶 { lua_getfield(L, -1, "name"); // 子table中name的值入栈 cout << "value: " << lua_tostring(L, -1) << endl; lua_pop(L, 1); // 弹掉 name lua_getfield(L, -1, "age"); // 子table中age的值入栈 cout << "age: " << lua_tonumber(L, -1) << endl; lua_pop(L, 1); // 弹掉 age } // lua_next会把key弹掉, 所以这里只要弹掉value(子table)即可恢复栈 lua_pop(L, 1); cout << "**********" << endl; } } lua_pop(L, 1); // 弹掉 g_t2 cout << "当前栈上数量 = " << lua_gettop(L) << endl; } return 0; } int setLuaVar_table_test(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into setLuaVar_table_test" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; // 创建表,压栈 lua_newtable(L); // 一对key value 入栈 // 压入key lua_pushstring(L, "name"); // 压入value lua_pushstring(L, "张三"); // 此时,表在栈底 // 弹出 key value 设置到表. 此时,表在栈顶了 lua_settable(L, 1); //------------------------------- // 一对key value 入栈 // 压入key lua_pushstring(L, "age"); // 压入value lua_pushinteger(L, 22); // 此时,表在栈底 // 弹出 key value 设置到表. 此时,表在栈顶了 lua_settable(L, 1); // 将此表设置为全局变量 lua_setglobal(L, "g_varTable"); cout << "当前栈上数量 = " << lua_gettop(L) << endl; return 0; } void callLuaFunc_simple(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into callLuaFunc_simple" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; const string luaFuncName = "luaSimpleFunc"; lua_getglobal(L, luaFuncName.c_str()); // 获取lua函数 if (lua_pcall(L, 0, 0, 0) != 0) // 调用失败 { // 失败会产生错误,这个错误会压栈。 这里把它出栈,以免内存泄露 cout << "call " << luaFuncName << " failed ! error = " << lua_tostring(L, -1) << endl; lua_pop(L, 1); } cout << "当前栈上数量 = " << lua_gettop(L) << endl; } void callLuaFunc_params_ret(lua_State *L) { cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into callLuaFunc_params_ret" << endl; cout << "当前栈上数量 = " << lua_gettop(L) << endl; const char* luaErrorFuncName = "fError"; lua_getglobal(L, luaErrorFuncName); // 获取lua错误处理函数 const char* luaFuncName = "luaParamsAndRetFunc"; lua_getglobal(L, luaFuncName); // 获取lua函数 lua_pushstring(L, "张三"); // 参数1 lua_pushinteger(L, 23); // 参数2 lua_newtable(L); // 参数3 // 表在栈中的位置 int tIdx = lua_gettop(L); // 压入key lua_pushstring(L, "score"); // 压入value lua_pushnumber(L, 91.5); // 弹出 key value 设置到表. 此时,表在栈顶了 lua_settable(L, tIdx); // 别忘了设置: 参数个数 、 返回值个数 、 错误处理函数在栈的位置 if (lua_pcall(L, 3, 2, -5) != 0) // 调用失败 { cout << "call " << luaFuncName << " failed ! error = " << lua_tostring(L, -2) << endl; // 失败会产生错误,这个错误会压栈。 这里把它出栈,以免内存泄露 lua_pop(L, 1); } else { // 获取返回值1 cout << "ret1 = " << lua_tostring(L, -2) << endl; // 获取返回值2 (table) // 这里演示直接获取字段值。 如要全表遍历,参考之前的代码 lua_getfield(L, -1, "name"); cout << "name = " << lua_tostring(L, -1) << endl; lua_pop(L, 1); lua_getfield(L, -1, "age"); cout << "age = " << lua_tointeger(L, -1) << endl; lua_pop(L, 1); // 这里把它出栈,以免内存泄露 lua_pop(L, 2); // 有2个返回值 } // 弹出错误处理函数,以免内存泄露 lua_pop(L, 1); cout << "当前栈上数量 = " << lua_gettop(L) << endl; } int main() { cout << " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> start <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl; // 创建状态机 lua_State *L = luaL_newstate(); // 打开基本库 luaL_openlibs(L); // 获取lua传递过来的普通参数测试 (给lua写的函数) lua_register(L, "simple_test", simple_test); // 获取lua传递过来的array参数测试 (给lua写的函数) lua_register(L, "array_test", array_test); // 获取lua传递过来的map参数测试 (给lua写的函数) lua_register(L, "map_test", map_test); // lua传递过来的参数类型检查测试 (给lua写的函数) lua_register(L, "checkType_test", checkType_test); // lua调用C++函数的返回值测试 (给lua写的函数) lua_register(L, "ret_test", ret_test); // lua调用C++函数的返回值(table)测试 (给lua写的函数) lua_register(L, "ret_table_test", ret_table_test); // 给lua传递c++全局变量值 (lua可用的C++全局变量) set2LuaVar_test(L); // 给lua传递c++全局变量值(table) (lua可用的C++全局变量) setLuaVar_table_test(L); // -------- 调用脚本前 --------- luaL_dofile(L, "test1.lua"); // -------- 调用脚本后 --------- // c++获取lua的全局变量值 (C++可用的lua全局变量) getLuaVar_test(L); // c++获取lua的全局变量值(table) (C++可用的lua全局变量) getLuaVar_table_test(L); // c++调用lua函数 callLuaFunc_simple(L); // c++调用lua函数(带参数和返回值) callLuaFunc_params_ret(L); // 关闭 lua_close(L); cout << " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> end <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"; return 0; }
test1.lua
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by saber.
--- DateTime: 2022/7/6 17:38
---
------------ array_test ---------------
local t1 = { "张三", "李四", "abc", "1234" }
array_test(t1)
-------------- map_test -------------
local t2 = { a = "张三", b = "李四", c = "abc", d = "1234" }
map_test(t2)
--------------- checkType_test ------------
checkType_test("abc", true)
------------- simple_test --------------
local score = simple_test("张三", 12)
print("score = ", score)
score = nil
------------- ret_test --------------
local ret1, ret2 = ret_test()
print("ret1 = ", ret1, " ret2 = ", ret2)
ret1 = nil
ret2 = nil
------------- ret_table_test --------------
local t3 = ret_table_test()
print("t3 = ", t3)
for i, v in pairs(t3) do
print(i .. " => " .. v)
end
t3 = nil
------------- getLuaVar_test --------------
g_var1 = 13.4
----------- getLuaVar_table_test -------------
g_t1 = {
name = "王五", age = 22,
}
g_t2 = {
{ name = "张三", age = 21 },
{ name = "王五", age = 22 },
{ name = "李明", age = 12 },
}
---------- set2LuaVar_test -------------
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lua get c++ global var")
print("c++ g_name = " .. g_name)
----------- setLuaVar_table_test ------------
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lua get c++ global table var")
print("g_varTable ==> ", g_varTable)
print("g_varTable name ==> " .. g_varTable["name"])
----------- callLuaFunc_simple -------------
function luaSimpleFunc1()
-- 测试错误用
--function luaSimpleFunc()
print("c++ call lua func simple")
end
---------------- callLuaFunc_params_ret -------------------
--function luaParamsAndRetFunc1(name, age, t) -- 测试错误用
function luaParamsAndRetFunc(name, age, t)
--function luaSimpleFunc()
print("c++ call lua params and ret func")
print("name = ", name, " age = ", age, " t = ", t, " t.score = ", t.score)
local retTable = { name = "saber", age = 20 }
return "this is a lua params_return func return", retTable
end
function fError(e)
print("原始Error = ", e)
return "这是自定义错误处理函数返回的错误,将覆盖原始返回的错误"
end



