Re: FFI metatypeof

  • From: Richard Hundt <richardhundt@xxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Tue, 12 Jun 2012 17:40:44 +0200

On Jun 12, 2012, at 4:10 PM, Mike Pall wrote:

> Richard Hundt wrote:
>> I'd like to get a reference to the metatable set via ffi.metatype()
>> far away from where it is set (for type checking, etc.).
> 
> Umm, why? There's already ffi.istype().

Actually, I reframed the problem and got caught on the precedence issue. 
Essentially what I'm trying to do is augment the cdata metatable with some 
methods which are common to all instances, and then still support overriding 
them:


local bit = require('bit')
local ffi = require('ffi')
ffi.cdef [[
typedef struct Foo { int answer; } Foo;
]]

local cmeta = debug.getmetatable(1LL)
local index = cmeta.__index
local cbase = { 
   lshift = function(a, b)
      return bit.lshift(tonumber(a), tonumber(b))
   end 
}
cmeta.__index = function(o, k)
   return cbase[k] or index(o, k)
end

local slots = { 
   lshift = function(a, b)
      return bit.lshift(tonumber(a.answer), tonumber(b))
   end 
}
local Foo = ffi.metatype('Foo', {
   __index = function(o, k)
      return slots[k]
   end 
})

local f = Foo(42)
print(f:lshift(1))

So because we're dispatching first to `cmeta.__index` then down to `slots`, Foo 
cannot override `lshift'. My previous attempt was to hook into `cmeta.__index` 
and try to get the metatable associated with the object and dispatch downward 
myself. This is hard to do using a registry table because `struct Foo*` and 
`struct Foo` can share a metatype, but ffi.typeof() returns different values 
for them.

I'll keep poking at it to see if I can come up with a workaround.

Thanks anyway.

Cheers,
Richard

Other related posts: