如何创建在调用某个函数时调用函数的函数?

Ope*_*ips 5 lua

我一直在尝试创建一个函数,一旦某个函数被调用,它就会运行一个事件/函数。我希望用法是这样的:

local a = nil

a = hookfunction(print, function() -- When print() is called...
    warn("print(...) called.") 
    return nil
end)
Run Code Online (Sandbox Code Playgroud)

我知道有一个 debug.sethook() 函数,但我不太知道如何使用它。

Pau*_*nko 1

有两种方法可以做到这一点,但每种方法都有一些您需要处理的陷阱。

一种方法是使用monkeypatching。这会将打印函数更改为另一个函数,该函数将执行您需要的操作,然后调用原始函数。

像这样的东西:

local origprint = print;
(_G or _ENV).print = function(...)
  io.write("print is called\n")
  return origprint(...)
end
print("foo", 1)
Run Code Online (Sandbox Code Playgroud)

这个选项的主要缺陷是,如果某个组件在进行猴子补丁之前保存了值print,那么它的后续使用将不会受到补丁的影响。

另一种选择是使用调试挂钩:

debug.sethook(function()
    local info = debug.getinfo(2)
    if info.name then
      io.write(info.name, " is called\n")
    end
  end, "c")
function foo()
  print("do something")
end
foo()
Run Code Online (Sandbox Code Playgroud)

这应该打印:

foo is called
print is called
do something
Run Code Online (Sandbox Code Playgroud)

这种方法的主要缺陷是它不能保证它会按照您的预期输出函数名称,因为这些值可能与它们的不同名称/容器相关联。

例如,这将打印a is called

local a = print
a("do something")
Run Code Online (Sandbox Code Playgroud)

这将打印? is called

local a = {print}
a[1]("do something")
Run Code Online (Sandbox Code Playgroud)