Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get multiple return values from function in Lua C API?

Tags:

c++

c

lua

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

like image 563
Zack Lee Avatar asked Jun 27 '19 07:06

Zack Lee


2 Answers

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

like image 75
YSC Avatar answered Sep 23 '22 12:09

YSC


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.

like image 27
user1810087 Avatar answered Sep 26 '22 12:09

user1810087