如何创建一个可重复生成的自定义require函数

我在Lua中创建了我的自定义require函数,但当我多次创建该函数时,它似乎无法替换先前创建的require函数。

我希望能够随时替换(或覆盖)以前的require函数。

我的代码:

#include "lua.hpp"

int main()
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    luaopen_my(L);
    lua_settop(L, 0);
    for (int i = 0; i < 2; ++i)
    {
        luaL_dostring(L, "local require_original = require\n"
                         "function require(name, ...)\n"
                             "print('Hello World')\n"
                             "local val = table.pack(require_original(name, ...))\n"
                             "return table.unpack(val,1,val.n)\n"
                         "end\n");
        luaL_dostring(L, "package.preload['A'] = function()\n"
                             "local a = {}\n"
                             "print('A required')\n"
                             "return a\n"
                         "end\n");
        luaL_dostring(L, "local a = require 'A'");
        luaL_dostring(L, "package.preload['A'] = nil package.loaded['A'] = nil");
    }
    lua_close(L);
}

我得到的结果 :

Hello World
A required
Hello World
Hello World
A required

我期望的结果 :

Hello World
A required
Hello World
A required

我应该更改什么以获得我期望的结果?

点赞
用户6834680
用户6834680

你可以在全局命名空间中提供特殊的“卸载”函数:-)

将第一个 luaL_dostring 中的 Lua 代码替换为以下代码:

if uninstall_my_require then
   uninstall_my_require()
end
local require_original = require
local function my_require(name, ...)
   print('Hello World')
   local val = table.pack(require_original(name, ...))
   return table.unpack(val,1,val.n)
end
require = my_require
function uninstall_my_require()
   if require == my_require then
      require = require_original
   end
   uninstall_my_require = nil
end
2018-08-08 10:39:32
用户369792
用户369792

第一次执行时,你正在将全局 require 函数设置为你的新函数,第二次执行时,你正在保存 你的新函数 并将它设置为另一个实例。在 Lua 中,就像这样:

local require_original1 = require
function require(name, ...)
   print('Hello World')
   local val = table.pack(require_original1(name, ...))
   return table.unpack(val,1,val.n)
end

local require_original2 = require -- 现在上面的函数
function require(name, ...) -- 再次重新定义
   print('Hello World')
   -- require_original2 是你上面的函数
   local val = table.pack(require_original2(name, ...))
   return table.unpack(val,1,val.n)
end

你需要跟踪原始 require 函数只需一次,可以使用像 Egor 的答案那样的卸载函数,也可以将它更改为仅分配一次的全局变量:

require_original = require_original or require
2018-08-08 18:37:48