如何创建可以重新创建的自定义要求

时间:2018-08-08 09:40:18

标签: c++ lua

我在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

要获得期望的结果,我应该改变什么?

2 个答案:

答案 0 :(得分:2)

您可以在全局名称空间中提供特殊的“卸载”功能:-)
用以下内容替换第一个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

答案 1 :(得分:2)

第一次将全局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 -- now the function above
function require(name, ...) -- redefine yet again
   print('Hello World')
   -- require_original2 is your function above
   local val = table.pack(require_original2(name, ...))
   return table.unpack(val,1,val.n)
end

您只需使用Egor的答案之类的卸载功能来跟踪原始的require函数一次,或者将其更改为仅分配一次的全局函数即可。

require_original = require_original or require