如何在Lua中要求已加载的模块。

我有一个 Lua 模块,它返回一个导出表(即不使用已弃用的 module 指令)。此外,我有一个想要通过“require”函数加载该模块的脚本。 现在我通过以下C代码将两个文件都加载到 Lua 状态中:

luaL_loadstring(lua, someScript);
lua_pcall(lua, 0, LUA_MULTRET, 0);
luaL_loadstring(lua, someModule);
lua_pcall(lua, 0, LUA_MULTRET, 0);

要求调用失败,因为它正在寻找文件,而不是已经加载的代码。在这种情况下,是否有可能在一些Script中从一些Module要求一些东西?

点赞
用户258523
用户258523

require 的文档 包含了所有你需要使其工作的信息。具体来说,它告诉你 require 函数使用了什么方法来查找所请求的代码。更具体地说,它的第一句话关于 package.loaded 是你可能需要注意的。

来自上述链接的文档:

加载给定的模块。该函数首先查看 package.loaded 表,以确定 modname 是否已经加载。如果已经加载,则 require 返回存储在 package.loaded[modname] 中的值。否则它会尝试查找该模块的加载器。

要找到加载器,require 根据 package.loaders 数组的指引进行。通过改变这个数组,我们可以改变 require 查找模块的方式。以下的解释是基于 package.loaders 的默认配置。

首先 require 查询 package.preload[modname]。如果它有值,这个值(应该是一个函数)就是加载器。否则 require 使用存储在 package.path 中的路径查找 Lua 加载器。如果这也失败了,它会使用存储在 package.cpath 中的路径查找 C 加载器。如果这也失败了,它会尝试使用 all-in-one 加载器(参见 package.loaders)。

一旦找到了一个加载器,require 就用一个参数 modname 调用这个加载器。如果加载器返回任何值,require 将返回的值分配给 package.loaded[modname]。如果加载器没有返回值并且没有分配任何值给 package.loaded[modname],则 require 将 true 分配给该条目。在任何情况下,require 都会返回 package.loaded[modname] 的最终值。

如果加载或运行模块时出现任何错误,或者无法找到该模块的任何加载器,则 require 会发出错误信号。

2014-01-21 18:30:10
用户869951
用户869951

为了清晰起见,让我们命名一些东西:模块A返回一个导出表;脚本B是一个字符串,需要模块A,我将假设B返回空。此外,您想要执行以下操作:

加载脚本B(通过luaL_loadstring):将块放在堆栈上
运行脚本B的块(通过lua_pcall):将B返回的任何内容放在堆栈上
加载模块A(通过luaL_loadstring):将块放在堆栈上
运行模块A(通过lua_pcall):将A返回的任何内容放在堆栈上

首先,模块A是一个文件,因此您可能已将A的内容加载到一个字符串中。

您说您的问题是在脚本B中调用的require失败了。可能有几个原因,例如B确实需要'moduleA',但是moduleA.lua在LUA_PATH文件夹中找不到。

所以:

  • 打印需要A的B部分,以便我们可以查看代码
  • 验证LUA_PATH是否可以找到moduleA.lua

一旦上述内容被确认为正确,我们可以查看您的C API调用,但我怀疑这些不是问题的原因。

2014-01-21 19:43:09
用户107090
用户107090

如果 someModule 使用 require"modname",则尝试以下代码:

lua_getglobal(lua, "package");
lua_getfield(lua, -1, "loaded");
luaL_loadstring(lua, someScript);
lua_pcall(lua, 0, 1, 0);
lua_setfield(lua, -2, modname);
luaL_loadstring(lua, someModule);
lua_pcall(lua, 0, LUA_MULTRET, 0);
2014-01-22 11:17:22