views:

176

answers:

2

Using C# and LuaInterface, I am trying to read a nested table, but am getting a null LuaTable when I try to open the key containing the table.

The .lua file:

DB = {
    ["inventory"] = {
        [10001] = {
            ["row"] = 140,
            ["count"] = 20,
        },
        [10021] = {
            ["row"] = 83,
            ["count"] = 3,
        },
        [10075] = {
            ["row"] = 927,
            ["count"] = 15,
        },
    }
}

I can successfully foreach the entries under inventory, by opening that table with:

LuaTable tbl = lua.GetTable("DB.inventory");
foreach (DictionaryEntry de in tbl)
...

What I cannot do is open an inventory item and enumerate its entries the same way. Is this because the key is a System.Double type? This fails:

LuaTable tbl = lua.GetTable("DB.inventory.10001");
foreach (DictionaryEntry de in tbl)

with an exception, because tbl is null.

Effectively, once I enumerate the keys (inventory items), I then want to drill down into the nested table and work with those contents. As you can see, I am not able to get a reference to the nested table the way I am doing it.

+1  A: 

I don't know about Luainterface, but the syntax

DB.Inventory.10001

is not valid syntax in standard Lua. Have you tried

DB.Inventory[10001]

which would be correct in standard Lua?

Norman Ramsey
Tried that, no change. tbl is still null.
Robert Kerr
Well, that `lua.GetTable` is nonstandard---I'd track down its documentation...
Norman Ramsey
+3  A: 

It appears that LuaInterface only supports string keys. From its Lua.cs, this function is eventually called by your code:

internal object getObject(string[] remainingPath) 
{
        object returnValue=null;
        for(int i=0;i<remainingPath.Length;i++) 
        {
                LuaDLL.lua_pushstring(luaState,remainingPath[i]);
                LuaDLL.lua_gettable(luaState,-2);
                returnValue=translator.getObject(luaState,-1);
                if(returnValue==null) break;    
        }
        return returnValue;    
}

Note that there is no provision for keys which aren't strings, because this code calls lua_pushstring() with part of the string that you indexed with.

The way LuaInterface takes a dot-delimited string argument to its operator[]() is deficient. You found one shortcoming; another would appear if you tried to look up a key that actually had a dot in it (which is legal Lua--though not idiomatic, there are times like you've discovered when the most natural way to express a key is not with something that looks like a C identifier).

What LuaInterface should provide is an indexing method taking types other than strings. Since it does not, you can rewrite your table like this:

DB = {
    ["inventory"] = {
        ["10001"] = {
            ["row"] = 140,
            ["count"] = 20,
        },
        ["10021"] = {
            ["row"] = 83,
            ["count"] = 3,
        },
        ["10075"] = {
            ["row"] = 927,
            ["count"] = 15,
        },
    }
}

I think this will work. Note that Norman Ramsey's suggestion, while entirely appropriate for proper Lua, will break in LuaInterface, so you should index with dots alone, as you were before (despite that this will look like a bug to any normal Lua programmer).

John Zwinck
I see. Wish I had influence over the lua table and I'd do as you suggested, changing the keys to strings.
Robert Kerr
Ouch. Assuming LuaInterface has a "execute this literal Lua code" feature, you could transform the table you have into the table you want. Basically just iterate over the table, building a new one with `tbl[tostring(key)] = value` (plus the logic to do this hierarchically).
John Zwinck