lua-users home
lua-l archive

[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!