pointerslualua-table

Lua table->address and address->table


Imagine the following code:

Mytable={}
print(Mytable)

Prints something like Table: 12345. How do I get the "address" part from Lua without messing with tostring's return value, and more importantly, how do I get the table back?

In code:

addr=table2address(Mytable)
-- type(addr) is number, addr is 12345
Othertable=address2table(addr)
-- type(Othertable) is table, Othertable==Mytable is true (same reference)

Is there any way to implement these 2 functions in Lua? If not, (how) do I do this in C?

Edit: the table2address could be done by cutting the Table: off from tostring(Mytable), but only if metamethod __tostring isn't defined, so I want to avoid this.


Solution

  • A trivial implementation meets all your criteria but one:

    function table2address(Mytable) return Mytable end
    function address2table(addr) return addr end
    

    demo:

    > Mytable={}
    > print(Mytable)
    table: 0x7fe511c0a190
    > addr = table2address(Mytable)
    > Othertable=address2table(addr)
    > =type(Othertable)
    table
    > print(Othertable==Mytable)
    true
    

    A slightly more complicated implementation meets all your criteria:

    t2at = {}
    
    function table2address(Mytable) 
      local addr = t2at[Mytable]
      if addr == nil then
        addr = #t2at + 1
        t2at[Mytable] = addr
        t2at[addr] = Mytable
      end
      return addr
    end
    
    function address2table(addr)
      return t2at[addr]
    end
    

    demo:

    > Mytable={}
    > addr = table2address(Mytable)
    > Othertable=address2table(addr)
    > =type(Othertable)
    table
    > print(Othertable==Mytable)
    true
    > =type(addr)
    number
    

    So, why is the address important to you?

    In a garbage collected language such as Lua, it is only possible to hold a reference to an object, not an address. [The present implementation may or may not move objects during GC, but other than userdata and Lua states, Lua has license to move anything.]

    ADDENDUM

    Re: "the addresses never get randomized (try print({}) in 2 new interactive lua instances)"

    e$ lua
    Lua 5.2.2  Copyright (C) 1994-2013 Lua.org, PUC-Rio
    > print({})
    table: 0x7fdaca4098c0
    > ^D
    e$ lua
    Lua 5.2.2  Copyright (C) 1994-2013 Lua.org, PUC-Rio
    > print({})
    table: 0x7fb02a4098c0
    > ^D
    e$ 
    

    Re: the physical address is really needed

    Look at the function luaL_tolstring that implements the guts of print; it has (in Lua 5.2.2):

      default:
        lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
                                            lua_topointer(L, idx));
        break;
    

    So, lua_topointer(L, idx) is the function you need to get a table's address.