2

I'm going to implement a function with C language and which will be called by Lua script.

This function should receive a lua table(which even contains an array) as the argument, so I should read the fields in the table.I try to do like below, but my function is crashing when I run it. Can anyone help my find the problem?


/*
 function findImage(options)
    imagePath = options.imagePath
    fuzzy = options.fuzzy
    ignoreColors = options.ignoreColor;
    ...
 end

 Call Example:

 findImage {
              imagePath="/var/image.png", 
              fuzzy=0.5,
              ignoreColors={
                             0xffffff, 
                             0x0000ff, 
                             0x2b2b2b
                           }
            }

 */

static int findImgProxy(lua_State *L)
{
    lua_settop(L, 1);
    luaL_checktype(L, 1, LUA_TTABLE);

    lua_getfield(L, -1, "imagePath");
    lua_getfield(L, -2, "fuzzy");
    lua_getfield(L, -3, "ignoreColors");

    const char *imagePath = luaL_checkstring(L, -3);
    double fuzzy    = luaL_optint(L, -2, -1);

    int count  = lua_len(L, -1); // how to get the member count of ignoreColor array

    int colors[count];
    for (int i=0; i count; i++) {
        lua_rawgeti(L, 4, i);
        colors[i] = luaL_checkinteger(L, -1);
        lua_pop(L, 1);
    }

    lua_pop(L, 2);

    ...
    return 1;
}

2 Answers 2

1

lua_len doesn't return anything, it only pushes the length on the stack. Use this snippet to get the table length:

lua_len(L, -1);
int count = luaL_checkinteger(L, -1);
lua_pop(L, 1);
Sign up to request clarification or add additional context in comments.

2 Comments

I tried use int count = lua_rawlen, which works.Am I right?
Yes, it works, too. Unlike lua_rawlen, lua_len has to push its result on stack because it may trigger __len metamethod, which may return anything from nil to userdata.
0
int count  = lua_len(L, -1); // how to get the member count of ignoreColor array

int colors[count];
for (int i=0; i count; i++)
{
    colors[i] = luaL_checkinteger(L, -1-i);
}

The code segment for this looks incorrect (never mind the missing comparision operator in the loop). The correct function for getting the table length is lua_objlen. It looks like you're trying to get the numbers out of 'ignoreColor' but you haven't place them on the stack first. As a result luaL_checkinteger(L, -1-i); ends up accessing the wrong indices on the stack.

You probably want something closer to this for example:

int count  = lua_objlen(L, -1);
std::vector<int> colors(count);
for (int i = 0; i < count; lua_pop(L, 1))
{
  lua_rawgeti(L, 4, ++i);
  colors.push_back( luaL_checkinteger(L, -1) );
}

If you're using Lua 5.2, replace lua_objlen with:

int count  = lua_rawlen(L, -1);

Make sure there's enough space on the stack if you're moving a lot of elements from the table. eg. lua_checkstack

4 Comments

lua_len is the correct function for getting the table length in Lua 5.2, though it performs an unnecessary metatable check.
@peterm arrrg they had to go and change the api up :( so annoying
@greatwolf, thank you for your help. I've edited my code above, could you have a look?
@Suge Note that variable length array's is an extension of gcc which is why I'm using vector in my example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.