在子目录中要求 LuaJIT 模块正在覆盖父目录中相同名称的模块。

我有一个文件夹的文件结构如下:

main.lua  (需要' mydir.b '和然后' b ')
b.lua
mydir/
  b.so    (LuaJIT C 模块)

从主函数中,我做了这个:

function print_loaded()
  for k, v in pairs(package.loaded) do print(k, v) end
end

print_loaded()
require 'mydir.b'
print_loaded()

-- 现在会包括'mydir.b',而不是'b':
local b = require 'b'

print的输出显示,我对require 'mydir.b'的调用将其返回值设置为package.loaded ['b']的值,以及期望的package.loaded ['mydir.b']。我希望将package.loaded ['b']保留为空,在以后可以require' b'而不会出现(在我看来)从mydir.b缓存值中无法正确缓存的情况。

我的问题是:如何处理这种情况?

在我这种情况下,我希望能够将mydir作为任何LuaJIT项目的子目录进行复制,而不必担心mydir.whatever通过破坏父目录级别的任何后续require,而污染模块名称空间。

为了预防人们说,“只是重命名你的模块!”是的。我可以做到这一点。但如果有一个更好的解决方案,使我根本不必担心名称冲突,那就太棒了。

点赞
用户3561
用户3561

问题在于我在 b.so 的源文件(b.c)中错误地调用了 luaL_register

这是造成问题的代码:

static const struct luaL_reg b[] = {
  /* 在这里设置函数指针列表 */
};

int luaopen_mydir_b(lua_State *L) {
  luaL_register(L, "b", b);  // <-- 问题在这里(详见下文)
  return 1;                  // 1 = # 在 Lua 中可见的返回值数量
}

上文代码中取得突出的这一行问题在于它将具体设置 package.loaded['b'] 的返回值为模块的返回值。这个问题可以通过改为以下代码解决:

luaL_register(L, "mydir.b", b);

上文代码将会将 package.loaded['mydir.b'] 设置为该模块的返回值,从而为后面使用不带前缀 mydir 的模块留出空间。

我一直到阅读了 LuaJIT 所依照的官方 Lua 5.1 文档 才终于明白这个问题。

2015-04-29 04:01:00