lua-users home
lua-l archive

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

Benoit Germain wrote:
> So now, in theory I have 3 types of closures that can be copied from
> one state to another:
> - pure Lua: the function proto is dumped out of the source state with
> lua_dump(), then loaded in the target state with luaL_loadbuffer, and
> the upvalues are transferred.
> - LuaJIT fast: the source function is converted to a string with
> tostring(), the entry is searched in a database stored in the target
> state's registry, and the upvalues are assigned the same way as above.
> - C functions: the C pointer is retrieved, the upvalues are pushed in
> the target state, then the closure is created with lua_pushcclosure().

Nope. You first try to lua_dump() it. If this fails, you use the
function as a key and look it up in the inverted table of standard
functions. If that fails then you have to punt. Simply copying C
functions between states is not safe. You shouldn't give users the
illusion this works.

> For the database, what I am doing now is this:
> Right after the state for a new lane has been created and its base
> libraries loaded, I perform a recursive search for non-Lua functions
> inside _G. I store string/func pairs, where the string is generated by
> tostring(func). This has the benefit of avoiding to hardcode the list
> of functions I want to store in the database. The drawback is that I
> need tostring() to be loaded in all lua_States, which is not
> necessarily the case (it is perfectly valid to create a lane with an
> empty lua state).

Err, no. tostring(func) may return different things in different
states. Use the module name plus the function name as an ID and
transfer that to the other state. Start from the list of loaded
modules, which is available on the C side via:
  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");

Also you only need the inverted table in states you copy _from_.
And only when lua_dump() fails. So you can lazily initialize that
table. This has the advantage that it works for extra C modules
which are loaded after startup, too. You could even load a module
in the target state with require(), if it's not there, yet.

> Now, I don't want to "remap" C functions that way, but only
> LuaJIT-fast functions. However, I can't reliably tell the difference
> between a C function and a LuaJIT-fast function.

Well, you really should remap _all_ library functions. Then you
don't need to tell them apart.