how to have lua call a c++ function that returns multiple values to lua

Viewed 250

my code (partial) c++:

lua_register(L, "GetPosition", lua_GetPosition);

int lua_GetPosition(lua_State* L)
{
    Entity e = static_cast<Entity>(lua_tointeger(L, 1));
    TransformComponent* trans = TransformComponentPool.GetComponentByEntity(e);
    if (trans != nullptr)
    {
        lua_pushnumber(L, trans->transform->position.x);
        lua_pushnumber(L, trans->transform->position.y);
        lua_pushnumber(L, trans->transform->position.z);
    }
    else
    {
        lua_pushnumber(L, 0);
        lua_pushnumber(L,0);
        lua_pushnumber(L, 0);
        LOG_ERROR("Transform not found");
    }
    return 1;
}

lua:

local x = 69
local y = 69
local z = 69
x,y,z = GetPosition(e)
print("xyz =",x,y,z)

I expected "xyz = 1.0 1.0 1.0" I got "xyz = 1.0 nil nil"

What's the right way to do this so lua sees all return values?

1 Answers

When Lua calls your function it will check its return value to find out how many values it should fetch from the stack. In your case that's 1. How else would Lua know how many of the pushed values you want to return?

From Lua 5.4 Reference Manual 4.6 Functions and Types:

In order to communicate properly with Lua, a C function must use the following protocol, which defines the way parameters and results are passed: a C function receives its arguments from Lua in its stack in direct order (the first argument is pushed first). So, when the function starts, lua_gettop(L) returns the number of arguments received by the function. The first argument (if any) is at index 1 and its last argument is at index lua_gettop(L). To return values to Lua, a C function just pushes them onto the stack, in direct order (the first result is pushed first), and returns in C the number of results. Any other value in the stack below the results will be properly discarded by Lua. Like a Lua function, a C function called by Lua can also return many results.

As an example, the following function receives a variable number of numeric arguments and returns their average and their sum:

 static int foo (lua_State *L) {
   int n = lua_gettop(L);    /* number of arguments */
   lua_Number sum = 0.0;
   int i;
   for (i = 1; i <= n; i++) {
     if (!lua_isnumber(L, i)) {
       lua_pushliteral(L, "incorrect argument");
       lua_error(L);
     }
     sum += lua_tonumber(L, i);
   }
   lua_pushnumber(L, sum/n);        /* first result */
   lua_pushnumber(L, sum);         /* second result */
   return 2;                   /* number of results */
 }
Related