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()

运行结果

 

posted @ 2025-07-10 23:15  yanghui01  阅读(38)  评论(0)    收藏  举报