I'm trying to create a SWIG typemap for a function that takes Lua table as an argument.
Here's my typemap which works fine with a table with number keys.
%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 = static_cast<lua_Integer>(lua_tointeger(L, -1));
if (!$1) SWIG_exception(SWIG_RuntimeError, "table is empty");
$2 = static_cast<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_isboolean(L, -1))
{
$2[i].a_type = A_FLOAT;
$2[i].a_w.w_float = static_cast<t_float>(lua_toboolean(L, -1));
}
else if (lua_isnumber(L, -1))
{
$2[i].a_type = A_FLOAT;
$2[i].a_w.w_float = static_cast<t_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");
}
}
}
%typemap(freearg) (int argc, t_atom *argv)
{
freebytes($2, $1 * sizeof(t_atom));
}
However, when the function takes tables with a string key.
It just prints SWIG_RuntimeError:table is empty
.
I would like to detect if the table has a string key before it prints this error.
I tried the following condition but it didn't work:
if (lua_type(L, -2) == LUA_TSTRING)
How can I properly detect if a table argument has at least one string key in a SWIG typemap?
Once you know the length of the table is 0 (which means it has zero
integer keys), you can fetch the next key-value pair with lua_next()
.
If it returns anything you know the tabel contains at least one non-integer
key.
/* table is in the stack at index 't',
* and is known to have no integer keys
*/
lua_pushnil(L); /* first key */
if (lua_next(L, t) != 0) {
/* Table contains non-integer key */
lua_pop(L, 2); /* throw away key-value pair */
/* Do stuff here */
}
They key can however be of type table or float or any other type that is alowed as a
key, so if you need to check explicitly for the occurrence of a string key
you will have to call lua_next()
in a loop and check the type of each
returned key until you find a string key or exhausts the loop.
has_stringkey = false;
/* table is in the stack at index 't' */
lua_pushnil(L); /* first key */
while (lua_next(L, t)) {
lua_pop(L, 1); /* throw away value */
if (lua_type(L, -1) == LUA_TSTRING) {
has_stringkey = true;
lua_pop(L, 1); /* throw away key before exit loop */
break;
}
}
if (has_stringkey) { /* do stuff */ }