Search code examples
luaswigluajit

What is lua_len() alternative in Lua 5.1?


I just replaced Lua with LuaJIT for my project and I got the error saying

Use of undeclared identifier 'lua_len'

How can I change lua_len so it is compatible with Lua 5.1 and LuaJIT?

Here's my code that uses lua_len from the SWIG binding. (In case it helps)

%typemap(in) (int argc, t_atom *argv)
{
    if (!lua_istable(L, $input)) {
      SWIG_exception(SWIG_RuntimeError, "argument mismatch: table expected");
    }
    lua_len(L, $input);
    $1 = lua_tointeger(L, -1);

    if (!$1) {
        SWIG_exception(SWIG_RuntimeError, "table is empty");
    }
    $2 = (t_atom *)getbytes($1 * sizeof(t_atom));

    for (int i=0; i<$1; ++i) {

        lua_pushinteger(L, i+1);
        lua_gettable(L, $input);

        if (lua_isnumber(L, -1)) {
            $2[i].a_type = A_FLOAT;
            $2[i].a_w.w_float = lua_tonumber(L, -1);
        }          
        else if (lua_isstring(L, -1)) {
            $2[i].a_type = A_SYMBOL;
            $2[i].a_w.w_symbol = gensym(lua_tostring(L, -1));
        }
        else {
            SWIG_exception(SWIG_RuntimeError, "unhandled argument type");
        }
    }
}

Solution

  • You can backport lua_len to Lua 5.1 by using lua-compat-5.3. If you don't want all of that, you can just use part of it by inlining it into your interface file. In case of lua_len you need

    %{
    static void lua_len (lua_State *L, int i) {
      switch (lua_type(L, i)) {
        case LUA_TSTRING:
          lua_pushnumber(L, (lua_Number)lua_objlen(L, i));
          break;
        case LUA_TTABLE:
          if (!luaL_callmeta(L, i, "__len"))
            lua_pushnumber(L, (lua_Number)lua_objlen(L, i));
          break;
        case LUA_TUSERDATA:
          if (luaL_callmeta(L, i, "__len"))
            break;
          /* FALLTHROUGH */
        default:
          luaL_error(L, "attempt to get length of a %s value",
                     lua_typename(L, lua_type(L, i)));
      }
    }
    %}