Zack Lee
Zack Lee

Reputation: 3074

How to create a custom require that can be recreated

I created my custom require function in Lua but when I create the function multiple times, it doesn't seem to replace the previously created require function.

I would like to be able to replace(or overwrite) the previous require function time to time.

My Code :

#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);
}

The Result I get :

Hello World
A required
Hello World
Hello World
A required

The Result I expect :

Hello World
A required
Hello World
A required

What should I change to get the result I expect?

Upvotes: 1

Views: 492

Answers (2)

Jason Goemaat
Jason Goemaat

Reputation: 29234

The first time through you are setting global require function to your new function, the second time you are saving your new function and setting it to another instance. It's like this in 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

You need to keep track of the original require function just once, either with an uninstall function like Egor's answer or change it to a global that is only assigned once:

require_original = require_original or require

Upvotes: 2

Egor   Skriptunoff
Egor Skriptunoff

Reputation: 974

You may provide special "uninstall" function in global namespace :-)
Replace Lua code inside first luaL_dostring with the following:

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

Upvotes: 2

Related Questions