lua-users home
lua-l archive

Re: require one C module from another

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


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!

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