lua-users home
lua-l archive

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

On Sat, Jun 6, 2009 at 11:02 AM, Wesley Smith<> wrote:
> Let's say you have a userdata that performs a callback into the
> lua_State based on events received C-side.  To actually do the
> callback, you need a pointer to the lua_State that the userdata
> belongs, which must be stored in the userdata.

Not so, when being called from lua, always use the L you were passed,
until the time that you return to lua, at which time you should assume
that L to be invalid.

In  the absence of co-routines, or multiple lua_States being created
from C, there tends to be only one lua_State, so you can be sloppy and
get away with storing L, and using it later because you always get
passed the same one, but its not right or necessary.

Say you have function make() that calls into C and stores a userdata.
And function dispatch() that calls into C, and in C code, based on
some event, calls a method on the userdata.

In make(), you store only the userdata.

In dispatch(), when calling the method, you use the lua state, L, that
you were passed.

What's more common is you have a c lib that that has
reg_callback(c_lib_ctx, c_cb_ptr, void* ctx)

The temptation is to pass L as ctx, then return to lua. Later, lua
calls back into C, and you do something to the C library that causes
it to make the callback, do_callbacks(c_lib_ctx). As you say, that L
may no longer be valid. But, the error was in letting the library hold
a ref to an object that should not be assumed valid for any length of

Instead, you should pass a pointer to a pointer to a lua state in
reg_callback, and before calling do_callbacks() you should put the L
that you were called with into a place where it is available to

Usually, what happens is that the module implemented in C that wraps
the C library creates its own ctx, including a lua_State* (which it
sets every time lua calls it), and some other various book keeping
refs, a pointer to the C libraries context/handle, refs to userdata,
refs to weak table which it can use to map C pointer values to lua
userdata, etc. It is that context which is used as the C callback
context, not a (possibly ephemeral) lua_State*.