5

I would like to know how to get multiple return values from function in Lua C API.

Lua Code:

function test(a, b)
  return a, b -- I would like to get these values in C++
end

C++ Code: (part where it calls the function)

/* push functions and arguments */
lua_getglobal(L, "test");  /* function to be called */
lua_pushnumber(L, 3);   /* push 1st argument */
lua_pushnumber(L, 4);   /* push 2nd argument */

/* call the function in Lua (2 arguments, 2 return) */
if (lua_pcall(L, 2, 2, 0) != 0)
{
    printf(L, "error: %s\n", lua_tostring(L, -1));
    return;
}
int ret1 = lua_tonumber(L, -1);
int ret2 = lua_tonumber(L, -1);
printf(L, "returned: %d %d\n", ret1, ret2);

The result I get:

returned: 4 4

The result I expect:

returned: 3 4

3
  • 1
    int ret1 = lua_tonumber(L, -1); should be int ret1 = lua_tonumber(L, -2); Commented Jun 27, 2019 at 7:33
  • 1
    lua_tonumber does not pop the value from the stack ... I'vent't check but I'm pretty sure. So perhaps lua_tonumber(L,-2) and lua_tonumber(L,-1) should do the trick Commented Jun 27, 2019 at 7:34
  • Note: Beyond the question, on the stack, you've got whatever results the function gave you for that particular call. You have to use the number of results to clean up the stack as needed, regardless of knowing what to do with them. Commented Jun 29, 2019 at 14:12

2 Answers 2

6

lua_tonumber does not alter the lua_State's stack. You need to read it at two different index1:

int ret1 = lua_tonumber(L, -2);
int ret2 = lua_tonumber(L, -1);
printf(L, "returned: %d %d\n", ret1, ret2);

Before you call test, your stack looks like this:

lua_getglobal(L, "test");  /* function to be called */
lua_pushnumber(L, 3);   /* push 1st argument */
lua_pushnumber(L, 4);   /* push 2nd argument */

|     4     |  <--- 2
+-----------+
|     3     |  <--- 1
+-----------+
|    test   |  <--- 0
+===========+

After its call2:

lua_pcall(L, 2, 2, 0) 

+-----------+
|     3     |  <--- -1
+-----------+
|     4     |  <--- -2
+===========+

An alternative would be to manually pop the results after you've read it:

int ret1 = lua_tonumber(L, -1);
lua_pop(L, 1);
int ret2 = lua_tonumber(L, -1);
lua_pop(L, 1);
printf(L, "returned: %d %d\n", ret1, ret2);

1) "If a function returns multiple results, the first result is pushed first; so, if there are n results, the first one will be at index -n and the last at index -1." Programming in Lua : 25.2

2) "Before pushing the results, lua_pcall removes from the stack the function and its arguments." Programming in Lua : 25.2

Sign up to request clarification or add additional context in comments.

Comments

4

You are taking the same index twice:

int ret1 = lua_tonumber(L, -1);
int ret2 = lua_tonumber(L, -1);

Stack is filled like this:

-- Lua
return a, b

+---+
| b | <-- top ("relative" index -1)
+---+
| a | <-- -2
+---+

So your C++ code should be:

// I don't know what ret1 or ret2 suppose to be.
// 1 = first on stack, or first return value?
// renamed to a and b for consistency with lua return a,b
int b = lua_tonumber(L, -1);
int a = lua_tonumber(L, -2);
// lua_pop(L, 2); // don't forget to pop the values

From 24.2.3 – Other Stack Operations :

[...]The lua_gettop function returns the number of elements in the stack, which is also the index of the top element. Notice that a negative index -x is equivalent to the positive index gettop - x + 1. [...]

This negative indeces positioning is valid for all Lua functions regarding the stack access, including lua_tonumber.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.