1

Is it possible to detect when the value of a variable has changed using the lua debug library. Something like A callback function which would give details like the function in which the value was changed, previous value, etc. Is such a thing possible?

I read about hooks, but I'm not sure hooks can be set to variables.

SatheeshJM
  • 3,575
  • 8
  • 37
  • 60
  • 1
    You could add custom setter methods to the metatable for the objects you are interested in. Have them alert you when run. – TheZ Aug 13 '12 at 20:41

2 Answers2

2

You can do this to a certain extent in Lua by using metatables and keeping a "proxy" table, and using the __newindex function call to detect attempts to add a variable.

This is covered here in the Programming in Lua book under the section "Tracking Table Accesses":

http://www.lua.org/pil/13.4.4.html

See Also
http://www.gammon.com.au/forum/?id=10887

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • thanks for the answer! That is good when accessing table elements. what if I need to track just a local variable/upvalue? – SatheeshJM Aug 13 '12 at 20:47
  • According to the "See Also" link I posted, tracking a local variable is not something that is really done in Lua, or for that matter in any other programming language, not without a debugger anyway. You might try having a look at Object Properties: http://lua-users.org/wiki/ObjectProperties, you can use that to make a setter that will notify you. – Robert Harvey Aug 13 '12 at 21:15
  • I've made a free library that provides this wrapper and notification for you. https://github.com/Phrogz/notifitable – Phrogz Feb 12 '14 at 07:04
  • 1
    Can this be used on the global environment (_G) as well? To prevent creation of global vars? And as a follow up, how 'safe' would that be (as I've read the _pairs_ function will not work?) – Gerald Eersteling Feb 25 '15 at 13:16
2

If you don't mind using a debugger, then some debuggers allow you to set Watch expressions, which will be triggered when the condition in the expression is true. I'll show how this can be done in MobDebug (it is using lua debug library, but there is no direct way to detect a variable change as far as I know).

Let say we have a script start.lua like the one below and want to detect where foo gets value 2:

print("Start")
local foo = 0
for i = 1, 3 do
  local function bar()
    print("In bar")
  end
  foo = i
  print("Loop")
  bar()
end
print("End")
  1. Download mobdebug.lua and make it available to your scripts (the simplest way is to put it into the folder with your scripts).
  2. Start the server using lua -e "require('mobdebug').listen()" command.
  3. Start the client using lua -e "require('mobdebug').loop()" command.
  4. You will see the prompt in the server window: '>'. Type load start.lua to load the script.
  5. Type step and then step again. You will see "Paused at file start.lua line 3".
  6. Let's see what the value of foo is. Type eval foo and you should see 0.
  7. Now we can set up our watch. Type setw foo == 2. You can specify any Lua expression after setw command; the execution of your script will be stopped when the condition is evaluated as true.
  8. Continue execution of the script using "run" command.
  9. The watch now fires, which will show you the message like: "Paused at file start.lua line 8 (watch expression 1: [foo == 2])". This means that the previous expression changed the value of foo to 2 and the execution is stopped at line 8. You can then inspect your script and the current values (you can use "eval" and "exec" commands to run any Lua code to be evaluated in your script environment) to find what triggered the change.

The benefit of this approach is that you are not limited to monitoring table values and can specify any expression. The main disadvantage is that your script runs under a debugger and the expression is evaluated after each step, which may get really slow.

Paul Kulchenko
  • 25,884
  • 3
  • 38
  • 56