Re: ffi: callback lifetime

  • From: Mike Pall <mike-1205@xxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Fri, 18 May 2012 14:46:37 +0200

Cosmin Apreutesei wrote:
> AFAIU implicit callback objects created by assigning a Lua function to
> a function pointer are internally anchored along with the Lua function
> and there's no way to access them or free them (or the Lua function).
> But callbacks created by ffi.cast() are not anchored and thus subject
> to normal garbage collection rules, and thus no need to "unanchor"
> them by cb:free(), is that right?

No, there's no difference between these. Callbacks are always
anchored independently and managed manually. That's why you need
to explicitly free them.

The only difference is that with implicit conversions, you can't
catch the callback function pointer in a variable, so you'll have
a hard time calling cb:free() on it. In other words: only the
explicit conversion with ffi.cast() allows you to free the
callback. Otherwise it'll never be freed (until the lua_close()).

> So if I pass some_lua_function where a function pointer is expected,
> the callback is permanent, but if I pass ffi.cast('WNDPROC',
> some_lua_function) the callback is only guaranteed to last until the
> function returns, and will be freed on the next gc cycle without me
> having to cb:free() it, right? Or do I always have to manually
> cb:free() it afterwards if I don't need it ? In other words, does a cb
> object have a __gc that does self:free() ?

Nope. Callbacks are never subject to GC. That's because in general
the VM cannot tell how long the C side may hold onto the callback
address. But you can tell -- by reading the docs. :-)

An allocated callback keeps the callback slot alive (there's a
limited number of these) as well as the Lua closure. If you free
the callback, the slot is immediately available again and the Lua
closure is now subject to regular GC (depends on whether it's
anchored somewhere else, too).

--Mike

Other related posts: