lua-users home
lua-l archive

Re: LuaJIT FFI __gc metamethod?

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Sunday 20, Josh Haberman wrote:
> I know metamethods for ctypes are a TODO, but I was just wondering if
> the __gc metamethod is one of the ones that will be supported? Or
> whether there's some reason why this would not be possible.
> 
> My use case is that I want to expose a refcounted C structure to Lua via
> the FFI. When Lua no longer needs the structure, I want to unref it
> using a C function.
You can wrap it in a newproxy() and set the __gc metamethod in the newproxy's 
metatable.
> One other question: I would prefer to make the Lua API for these
> structure members look like regular field accesses, ie:
> 
> -- User doesn't know it, but foo is actually a ctype.
> foo = MyStructure()
> print(foo.bar)
> foo.bar = 5
> 
> However I need to hook in some of my own code in some of these
> operations, like when "foo.bar = 5" happens I need it to also execute
> "foo.has_bar = true", where has_bar is a separate structure member.
> I could do this as a function:
> 
> function MyStructure:set_bar(bar)
> self.bar = bar
> self.has_bar = true
> end
> 
> I guess I'm wondering if there is any way to get this same efficiency
> (since I expect LuaJIT FFI will optimize set_bar to be basically perfect)
> while providing users the "foo.bar = 5" syntax instead of foo:set_bar(5).
> If not, I'll just go with the method syntax, since I don't want to paint
> myself into an efficiency corner just to get nicer syntax.
How about something like this?
-- warning un-tested code.
function MyStructure()
 -- create cdata
 local cdata = ffi.new('MyStructure')
 local self = newproxy(true)
 local meta = getmetatable(self)
 meta.cdata = cdata
 -- maybe '__index' can set to 'cdata'
 meta.__index = function(tab, key)
 return cdata[key]
 end
 meta.__newindex = function(tab, key, value)
 cdata[key] = value
 cdata["has_" .. key] = true
 end
 meta.__gc = function()
 -- TODO: unref cdata.
 end
 return self -- we return the newproxy() object here, not the cdata.
end
-- 
Robert G. Jakabosky

AltStyle によって変換されたページ (->オリジナル) /