'get the address of a lua object

When you print certain types in lua (such as functions and tables), you get the name of the type and an address, as below:

> tab = {}
> print(tab)
table: 0xaddress

I have created a simple class as below, and I would like to override the __tostring method similarly. How do I get the address of the object that I want to print?

Here's my class. I would like print(pair) to print out Pair: 0xaddress. Obviously this is a trivial example, but the concept is useful:

Pair = {}
Pair.__index = Pair

function Pair.create()
 local p = {}
 setmetatable(p, Pair)
 p.x = 0
 p.y = 0
 return p
end

function Pair:getx()
 return self.x
end

function Pair:gety()
 return self.y
end

function Pair:sety(iny)
 self.y=iny   
end

function Pair:setx(inx)
 self.x=inx
end


Solution 1:[1]

Here's a hokey way to do it:

Pair.__tostringx = function (p)
    Pair.__tostring = nil    
    local s = "Pair " .. tostring(p)                                                                                                                                                                                                    
    Pair.__tostring = Pair.__tostringx
    return s
end
Pair.__tostring = Pair.__tostringx    

> print(p)
Pair table: 0x7fe469c1f900

You can do more string manipulation inside Pair.__tostringx to get the format you want, e.g., to remove "table".

Solution 2:[2]

I think that the __tostring() that prints table: 0xaddress isn't actually implemented in straight Lua. I looked around a bunch, but the only way I could think to do it isn't exactly what you were thinking. I added a function to the Pair class called toString that uses the default __tostring() to get the normal string, then takes out "table" and puts in "Pair".

function Pair:toString()
    normalPrint = tostring(self)
    return ("Pair:" .. normalPrint:sub(7))
end

pair = Pair.create()
print(pair:toString())

Then you call Pair:toString() to get the properly formatted output. You can't do this while overriding __tostring because you'll have a hard time accessing the super's __tostring, and if you call Pair's __tostring, a stack overflow occurs from the recursion.

Solution 3:[3]

Not the same syntax you used, but works: (However could be polished)

Pair = {}
Pair.address = string.gsub(tostring(Pair), "table:", "") --Gets the original address as a string.
local metas = {
    __tostring = function(tab)
        return "Pair:" .. tab.address
    end 
}
setmetatable(Pair, metas)
print(Pair) --Will print Pair: 0xaddress

Solution 4:[4]

You can use __name in Lua 5.3 or higher.

print(tostring(setmetatable({}, {__name = "Pair"})))

it prints:

Pair: 0x5575ef88cf50

Solution 5:[5]

local function f() end
local t = {}

print(f, t)
print(string.format("%p\t%p", f, t))

--[[
function: 0x8813c0  table: 0x881810
0x8813c0    0x881810
]]

Tested on https://www.lua.org/demo.html.

Solution 6:[6]

Try

function rawstr(t)
  local mt = getmetatable(t)
  local save_tostring
  if mt and mt.__tostring then
     save_tostring = mt.__tostring
     mt.__tostring = nil
  end
  local raw = tostring(t)
  if save_tostring then
    mt.__tostring = save_tostring
  end
  return raw
end

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Doug Currie
Solution 2 boztalay
Solution 3 HackNoobLixo
Solution 4 JE42
Solution 5
Solution 6 Mike Blyth