I have been trying to create a function that runs an event/function once a certain function is called. I want the usage to be like this:
local a = nil
a = hookfunction(print, function() -- When print() is called...
warn("print(...) called.")
return nil
end)
I know there is a debug.sethook() function, but I don't quite know how to use it.
There are two ways to do this, but each has some pitfalls you need to deal with.
One way is to use monkeypatching. This will change the print function to a different function that will do what you need and then call the original function.
Something like this:
local origprint = print;
(_G or _ENV).print = function(...)
io.write("print is called\n")
return origprint(...)
end
print("foo", 1)
The main pitfall with this option is that if some component saves the value of print
before it's monkeypatched, the subsequent usage of it is not going to be affected by your patch.
Another option is to use debug hook:
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()
This should print:
foo is called
print is called
do something
The main pitfall with this approach is that it doesn't guarantee that it will output the function name as you'd expect, because the values may be associated with different names/containers for them.
For example, this will print a is called
:
local a = print
a("do something")
And this will print ? is called
:
local a = {print}
a[1]("do something")
Simplest way would be to wrap the original function:
do
local _print = print
function print(...)
_print("print(...) called.")
_print(...)
end
end
print("hello world")
output:
print(...) called.
hello world
what we did hear was stored the original print
in a local variable _print
which is an upvalue to the new global print function we created after storing the orginal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With