如何在 Lua C 扩展函数中确定 Lua 期望返回的值数量

每次调用 Lua 函数时,调用站点(call site)都可以立即知道返回值的数量:

f() --0
local a, b = f() --2
local t = {f()} --LUA_MULTRET
local t = {f(), nil} --1

C API 中也是如此:lua_calllua_pcall 总是会知道期望的返回值数量(或 LUA_MULTRET)。

考虑性能,有时候一个 Lua 函数能够确定调用它的函数期望的返回值数量可能很有优势,这样可以避免计算调用者未请求的返回值(如果计算时间很长):

int getstrings(lua_State *L)
{
    if(lua_numresults(L) > 0)
    {
        lua_pushstring(L, "a");
        if(lua_numresults(L) > 1)
        {
            lua_pushstring(L, "b");
            if(lua_numresults(L) > 2)
            {
                lua_pushstring(L, "c");
                return 3
            }
            return 2;
        }
        return 1
    }
    return 0;
}

假设一个假想的 lua_numresults 返回 size_t,这个函数将只生成真正需要的返回值,而不会计算保证会丢失的返回值。

另一个有趣的例子是返回序列的函数:

int range(lua_State *L)
{
    size_t num = lua_numresults(L);
    for(size_t i = 1; i <= num; i++)
    {
        lua_pushinteger(L, i);
    }
    return num;
}

这个序列不是“惰性”的,所以像 f(range()) 这样的函数调用无法完成,但 local a, b, c = range() 将返回 1、2、3 等可能很有用。

是否有类似 lua_numresults 的功能或者实现其功能的方法?

点赞
用户1424244
用户1424244

根据 Lua 5.3 的源代码来看,期望的结果数量位于 CallInfo 结构体中。每次 Lua 调用都会创建一个新的调用信息(call info),最近的一个信息存储在 lua_State::ci 中。似乎没有任何函数可以返回这个值,但如果有人可以访问这个结构,那么获取它就相当简单了:

#include "lua/lstate.h"

size_t lua_numresults(lua_State *L)
{
    return (size_t)L->ci->nresults;
}
2018-08-20 15:26:01