Zack Lee
Zack Lee

Reputation: 3074

How to get multiple returned tables from Lua function?

I'm trying to send multiple float arrays from C++ to Lua function as arguments and then return multiple tables from the function so I can use them again as float arrays in C++.

So my Lua function will look like this.

function perform(arg1, arg2)
    local ret1, ret2 = {}, {}
    for i=1, #arg1 do
        ret1[i] = arg1[i] * 0.2;
        ret2[i] = arg2[i] * 0.3;
    end
    return ret1, ret2
end

And this is how I send and return multiple tables to/from Lua function in C++.

lua_getglobal(L, "perform");

for (int i=0; i<numArgs; ++i) {

    lua_newtable(L);
    float *in = reinterpret_cast<float*>(w[i]);

    for (int j=0; j<64; ++j) {

        lua_pushinteger(L, j+1);
        lua_pushnumber(L, in[j]);
        lua_settable(L, -3);
    }
}
lua_call(L, numArgs, numRets);

for (int i=0; i<numRets; ++i) {

    float *out = reinterpret_cast<float*>(w[numArgs+i]);

    for (int j=0; j<64; ++j) {

        lua_pushinteger(L, j+1);
        lua_gettable(L, -2);
        out[j] = lua_tonumber(L, -1);
        lua_pop(L, 1);
    }
    //how to detect next returned table?
}

But if I try the code, the returned arrays have same values.

I think it's because I'm not correctly getting the returned tables.

Could anybody please teach me how to get multiple returned tables correctly?

P.S: I would also like to know if my code can be optimized for better performance.

EDIT : Would it be faster(more efficient) to pass and return one table that has multiple sub-tables? If so, I'd appreciate if anyone can teach me how to do it.

Upvotes: 1

Views: 647

Answers (1)

Henri Menke
Henri Menke

Reputation: 10939

I have no idea what you are trying to do here, but the second table returned from the function is easily accessible on the stack. You just have to perform some arithmetic on the stack index to get to the correct position.

Those reinterpret_casts look extremely fishy to me. You are quite likely to be doing something wrong.

#include <iostream>
#include <vector>

#include <lua.hpp>

int main(int argc, char *argv[]) {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);

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

    luaL_dofile(L, argv[1]);

    // Mock data
    int numArgs = 2;
    int numRets = 2;
    std::vector<float> w1(64, 1.0f);
    std::vector<float> w2(64, 1.0f);
    std::vector<float> w3(64, 1.0f);
    std::vector<float> w4(64, 1.0f);
    std::vector<float *> w = {w1.data(), w2.data(), w3.data(), w4.data()};

    lua_getglobal(L, "perform");

    for (int i = 0; i < numArgs; ++i) {

        lua_newtable(L);
        float *in = reinterpret_cast<float *>(w[i]);

        for (int j = 0; j < 64; ++j) {
            lua_pushinteger(L, j + 1);
            lua_pushnumber(L, in[j]);
            lua_settable(L, -3);
        }
    }

    lua_call(L, numArgs, numRets);

    for (int i = 0; i < numRets; ++i) {

        float *out = reinterpret_cast<float *>(w[numArgs + i]);

        for (int j = 0; j < 64; ++j) {
            lua_pushinteger(L, j + 1);
            lua_gettable(L, -2 - i); // Just some stack index arithmetic
            out[j] = lua_tonumber(L, -1);
            lua_pop(L, 1);
        }
    }

    lua_close(L);
}

Upvotes: 1

Related Questions