要求子目录中的 LuaJIT 模块会覆盖父目录中的同名模块

Posted

技术标签:

【中文标题】要求子目录中的 LuaJIT 模块会覆盖父目录中的同名模块【英文标题】:Requiring a LuaJIT module in a subdir is overwriting a module of the same name in the parent dir 【发布时间】:2015-07-04 10:18:00 【问题描述】:

我有这样的文件设置:

main.lua  (requires 'mydir.b' and then 'b')
b.lua
mydir/
  b.so    (LuaJIT C module)

从main开始,我这样做:

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

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

-- This would now include 'mydir.b' instead of 'b':
local b = require 'b'

prints 的输出表明我对require 'mydir.b' 的调用将返回值设置为package.loaded['b'] 的值以及预期的package.loaded['mydir.b']。我想让package.loaded['b'] 保持未设置,以便我以后可以require 'b' 而不是最终得到来自mydir.b 的(我认为不正确的)缓存值。

我的问题是:有什么好的方法来解决这个问题?

就我而言,我希望能够将mydir 复制为我的任何LuaJIT 项目的子目录,而不必担心mydir.whatever 会通过销毁以后的requires 来污染模块命名空间whatever 在父目录级别。

预期人们会说,“只需重命名您的模块!”是的。我能做到。但我很想知道是否有更好的解决方案让我根本不必担心名称冲突。

【问题讨论】:

你的b.lua是否有机会使用module函数? 不,它没有。此行为似乎与b.lua 的内容无关。 b.so 库是否在任何地方设置了packages.loaded(例如使用module)? 不,b.so 不会在任何地方使用module。但!它确实调用了luaL_register,这可能是导致问题的原因!感谢您帮助我意识到这一点。我会写一个答案。 【参考方案1】:

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

这是导致问题的错误代码:

static const struct luaL_reg b[] = 
  /* set up a list of function pointers here */
;

int luaopen_mydir_b(lua_State *L) 
  luaL_register(L, "b", b);  // <-- PROBLEM HERE (see below)
  return 1;                  // 1 = # Lua-visible return values on the stack.

突出显示的行的问题在于,它会专门设置package.loaded['b'] 以在加载此模块时具有该模块的返回值。这可以通过将行替换为以下内容来解决:

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

这将改为设置package.loaded['mydir.b'],从而为以后使用同名模块(不带mydir前缀)留出空间。

直到我问了这个问题很久之后我才意识到这一点,当我终于有时间阅读 Lua 5.1 的官方 docs for luaL_register 时,这是 LuaJIT 所遵循的版本。

【讨论】:

IIRC,luaopen_whatever() 是使用 require() 中的单个 modname 参数调用的,因此使用它而不是硬编码名称可能更正确。 或使用lua_newtable(L); luaL_register(L, NULL, b);。从模块内设置全局变量不是最佳实践any more。一个名为 mydir.b 的全局变量无论如何都不会那么有用,因为您必须编写 _G["mydir.b"] 才能实际使用它。

以上是关于要求子目录中的 LuaJIT 模块会覆盖父目录中的同名模块的主要内容,如果未能解决你的问题,请参考以下文章

从 Cloud Functions 中的父目录或同级目录导入模块?

使用本地目录覆盖 virtualenv 中的模块

如何使用位于父目录中的 eslint 插件模块?

对如何从模块中的其他目录/父目录导入感到困惑(python 3)

maven多模块项目中的模块级声纳分析

SBT 中的排序和覆盖任务