0

I wonder if it is possible to dynamically find out the number of return values of Lua function in C++.

For example, I can pass and return values to/from Lua function in C++ like this.

/* push functions and arguments */
lua_getglobal(L, "f");  /* function to be called */
lua_pushnumber(L, x);   /* push 1st argument */
lua_pushnumber(L, y);   /* push 2nd argument */

/* do the call (2 arguments, 1 result) */
if (lua_pcall(L, 2, 1, 0) != 0)
    error(L, "error running function `f': %s", lua_tostring(L, -1));

/* do something with the result */

As you can see, it expects 1 returned value from Lua function. So if user returns more(or less) than 1 value in Lua function, it will not work properly.

Is there any possible solution to detect the number of returned values from Lua function in advance so I can dynamically process the returned values in C++?

Zack Lee
  • 2,784
  • 6
  • 35
  • 77
  • Possible duplicate of [How can I know return value count of a Lua function from C?](https://stackoverflow.com/questions/6434610/how-can-i-know-return-value-count-of-a-lua-function-from-c) – Henri Menke Jun 19 '18 at 09:46
  • It shouldn't be a problem if it returns more, right? And, ICYDK, it could return a different number with each call. – Tom Blodget Jun 19 '18 at 16:37

2 Answers2

3

This is an extension to the existing answer, outlining a possible implementation. I will remove this answer as soon as an implementation example is added to the existing one.

#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
Henri Menke
  • 10,705
  • 1
  • 24
  • 42
  • Please help me Sir. https://stackoverflow.com/questions/51063716/how-to-get-returned-table-from-lua-function-in-c – Zack Lee Jun 28 '18 at 01:32
2

https://www.lua.org/manual/5.3/manual.html#lua_call (also applies to lua_pcall):

The number of results is adjusted to nresults, unless nresults is LUA_MULTRET. In this case, all results from the function are pushed; Lua takes care that the returned values fit into the stack space, but it does not ensure any extra space in the stack. The function results are pushed onto the stack in direct order (the first result is pushed first), so that after the call the last result is on the top of the stack.

So it looks like you can save the previous stack top (use lua_gettop), subtract the number of arguments and 1 for function itself, do the call, then get the stack top again and the difference is the number of return values. Remember to pass LUA_MULTRET for nresults.

user253751
  • 57,427
  • 7
  • 48
  • 90