[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: require one C module from another
- From: Josh Haberman <jhaberman@...>
- Date: Fri, 20 Jun 2014 11:32:08 -0700
On Thu, Jun 19, 2014 at 8:28 PM, Jay Carlson <nop@nop.com> wrote:
> The easiest thing is to support only one Lua state.
> You can use static variables like
> "has_started_initializing" and "has_finished_initializing"
Writing a module that can only work with one Lua state would be very
limiting -- definitely not a route I want to go!
> or whatever will break the circular dependency.
I must have given the impression that I have a circular dependency
since several people have mentioned this. I don't have any circular
dependencies in my modules, just dependencies between two C modules.
> Section 28.3 of _Programming in Lua, 3ed_ suggests
> casting the address of a static variable in your C code
> to a lightuserdata, and using that as an index for the
> current state's registry.
I like this very much! It appears to be a basically-perfect (ie. very
robust) way of implementing at-most-once-per-Lua-state loading of a C
module, regardless of what require() is or is not doing:
int luaopen_mymod(lua_State *L) {
static char module_key;
// Lookup cached module table.
lua_pushlightuserdata(L, &module_key);
lua_rawget(L, LUA_REGISTRYINDEX);
if (!lua_isnil(L, -1)) {
// Return cached module table.
return 1;
}
luaL_newlib(L, myfuncs);
// Save module table in cache.
lua_pushlightuserdata(L, &module_key);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
// ... Other one-time initialization.
// Return new module table.
return 1;
}
This will work in all cases, even if a user very directly calls
package.loadlib() twice on your module.
Other C modules could delete your key from the registry, but this is
an openly hostile thing to do, and C modules have plenty of other ways
ways to exercise open belligerence.
Thanks for the suggestion!