Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create a function that calls a function when a certain function is called?

Tags:

lua

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.

like image 814
OpenGamerTips Avatar asked Oct 16 '22 04:10

OpenGamerTips


2 Answers

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")
like image 149
Paul Kulchenko Avatar answered Oct 21 '22 08:10

Paul Kulchenko


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.

like image 34
Nifim Avatar answered Oct 21 '22 08:10

Nifim