lua c api - lua_pcall, lua_call
错误处理函数(c代码)
// Lua错误处理函数 static int c_traceback(lua_State *L) { //栈上的元素: { errMsg } //相当于debug.traceback lua_getglobal(L, "debug"); //栈[LUA_GLOBALSINDEX]["debug"]处的元素压入栈顶 lua_getfield(L, -1, "traceback"); // debug["traceback"]处的元素压入栈顶 lua_pushvalue(L, 1); // 错误消息, 栈底元素再压入栈顶 lua_pushinteger(L, 2); // 堆栈层级, 忽略掉c_traceback和TestPcall调用层级 //栈上的元素: { errMsg, debug, debug.traceback, errMsg, 2 } //调用栈[-3]处的函数: 2个参数, 1个返回值; 相当于调用 debug.traceback(errMsg, 2) //执行完栈顶弹出3个元素, 返回值压入栈顶 lua_call(L, 2, 1); //栈上的元素: { errMsg, debug, tracebackMsg } return 1; }
示例1
static int TestPcall(lua_State* L) { //栈上的元素: { param1(1), param2(nil) } lua_pushcfunction(L, c_traceback); lua_insert(L, 1); //栈顶元素insert在栈底, 栈上的元素: { c_trackback, param1(1), param2(nil) } lua_getglobal(L, "divide"); //栈[LUA_GLOBALSINDEX]["divide"]处的元素压入栈顶 //栈上的元素: { c_traceback, param1(1), param2(nil), divide } lua_insert(L, 2); //栈顶元素insert在栈[2]处 //栈上的元素: { c_traceback, divide, param1(1), param2(nil) } //调用栈[-3]处的函数: 2个参数(栈[-2], 栈[-1]), 1个返回值, 错误处理函数在栈[1]; 相当于调用 divide(1, nil) //执行完栈顶弹出3个元素, 返回值压入栈顶 int code = lua_pcall(L, 2, 1, 1); if (0 != code) { //栈上的元素: { c_traceback, tracebackMsg } fprintf(stderr, "----- %s\n", lua_tostring(L, -1)); lua_pop(L, 2); // 清理错误信息和处理函数 lua_pushnil(L); //栈上的元素: { nil } return 1; //栈顶弹出1个元素, 作为lua层拿到的返回值 } else { //栈上的元素: { c_traceback, result1 } return 1; //栈顶弹出1个元素, 作为lua层拿到的返回值 } }
static const struct luaL_reg mylib_funcs[] = { {"TestPcall", TestPcall}, {0, 0} }; LUALIB_API int luaopen_mylib(lua_State *L) { // 栈上的元素: { "mylib" } luaL_openlib(L, "mylib", mylib_funcs, 0); //新建表mylib, 压入栈顶, 将表保存在: 栈[LUA_GLOBALSINDEX]["mylib"] = mylib, 函数注册在mylib下 // 栈上的元素: { "mylib", mylib表 } return 1; //栈顶弹出1个元素, 作为lua层拿到的返回值 }
lua测试代码
function divide(a, b) print("lua:divide", a, b) local c = a / b return c end local function Test6() local curl = require("mylib") print(curl.TestPcall(1, 2)) print(curl.TestPcall(1, nil)) end
运行结果
示例2
static int TestPcall2(lua_State* L) { //栈上的元素: { param1(3) } lua_pushcfunction(L, c_traceback); lua_insert(L, 1); //栈顶元素insert在栈底, 栈上的元素: { c_trackback, param1(3) } lua_getglobal(L, "MultiRet"); //栈[LUA_GLOBALSINDEX]["MultiRet"]处的元素压入栈顶 //栈上的元素: { c_traceback, 2, nil, MultiRetFun } lua_insert(L, 2); //栈顶元素insert在栈[2]处 //栈上的元素: { c_traceback, MultiRetFun, param1(3) } //调用栈[-2]处的函数: 1个参数(栈[-1]), 多个返回值, 错误处理函数在栈[1]; 相当于调用 MultiRetFun(3) //执行完栈顶弹出2个元素, 返回值压入栈顶 int code = lua_pcall(L, 1, LUA_MULTRET, 1); if (0 != code) { //栈上的元素: { c_traceback, tracebackMsg } fprintf(stderr, "----- %s\n", lua_tostring(L, -1)); lua_pop(L, 2); // 清理错误信息和处理函数 lua_pushnil(L); //栈上的元素: { nil } return 1; //栈顶弹出1个元素, 作为lua层拿到的返回值 } else { //栈上的元素: { c_traceback, result1(3), result2(2), result3(1) } int resultNum = lua_gettop(L) - 1; return resultNum; //栈顶弹出n个元素, 作为lua层拿到的返回值 } }
lua测试代码
function MultiRet(n) print("lua:MultiRet", n) local list = {} for i=n,1,-1 do table.insert(list, i) end return unpack(list) end local function Test7() local curl = require("mylib") print(curl.TestPcall2(3)) print(curl.TestPcall2(nil)) end Test7()
运行结果