动态获取 Lua 函数返回值的数量?

我想知道在 C++ 中,是否有可能动态获取 Lua 函数返回值的数量。

例如,我可以像这样在 C++ 中向 Lua 函数传递和返回值:

/* 压入函数和参数 */
lua_getglobal(L, "f");  /* 被调用的函数 */
lua_pushnumber(L, x);   /* 压入第一个参数 */
lua_pushnumber(L, y);   /* 压入第二个参数 */

/* 调用函数(2个参数,1个返回值) */
if (lua_pcall(L, 2, 1, 0) != 0)
    error(L, "运行函数`f`时出错:%s", lua_tostring(L, -1));

/* 对返回值进行处理 */

可以看到,它期望从 Lua 函数返回 1 个值。因此,如果用户在 Lua 函数中返回的值多于(或少于)1 个,则它将无法正常工作。

是否有可能事先检测 Lua 函数返回值的数量,以便我可以在 C++ 中动态处理返回值?

点赞
用户106104
用户106104

除非 nresults 为 LUA_MULTRET,否则结果个数将调整为 nresults。在此情况下,将推入函数返回的所有结果;Lua 确保返回的值适合栈空间,但不保证栈中有额外的空间。函数结果按直接顺序推入堆栈(首个结果先被推入),因此在调用之后,最后一个结果位于堆栈顶部。

因此,您可以保存以前的堆栈顶部(使用lua_gettop),减去参数数量和 1 个函数本身,执行调用,然后再次获取堆栈顶部,差异即为返回值数量。记得为 nresults 传递 LUA_MULTRET。

2018-06-19 04:28:57
用户1944004
用户1944004

这是对现有答案的扩展,阐述了一种可能的实现方式。一旦现有答案添加实现示例,我将删除此答案。

#include <iostream>

#include <lua.hpp>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " <script.lua>\n";
        return 1;
    }

    lua_State * L = luaL_newstate();
    luaL_openlibs(L);

    if (luaL_dofile(L, argv[1]) != 0) {
        std::cerr << "lua: " << lua_tostring(L, -1) << '\n';
        lua_close(L);
        return 1;
    }

    int stack_size = lua_gettop(L);

    lua_getglobal(L, "f");
    lua_pushnumber(L, 1);
    lua_pushnumber(L, 2);

    if (lua_pcall(L, 2, LUA_MULTRET, 0) != 0) {
        std::cerr << "lua: " << lua_tostring(L, -1) << '\n';
        lua_close(L);
        return 1;
    }

    int num_returns = lua_gettop(L) - stack_size;
    std::cout << num_returns << " values returned\n";

    lua_close(L);
}
function f(x,y)
    return 1,2,3,"Hello World",{},function() end
end
6 values returned
2018-06-19 09:45:09