0

I'm implementing Lua scripting in my game using LuaBind, and one of the things I'm not clear on is the logistics of reloading the scripts live ingame.

Currently, using the LuaBind C++ class luabind::object, I save references to Lua callbacks directly in the classes that use them. Then I can use luabind::call_function using that object in order to call the Lua code from the C++ code.

I haven't tested this yet, but my assumption is that if I reload the scripts, then all the functions will be redefined, BUT the references to the OLD functions will still exist in the form of the luabind::object held by the C++ code. I would like to be able to swap out the old for the new without manually having to manage this for every script hook in the game.

How best to change this so the process works?

My first thought is to not save a reference to the function directly, but maybe save the function name instead, and grab the function by name every time we want to call it. I'm looking for better ideas!

Raptormeat
  • 312
  • 2
  • 14

1 Answers1

2

My first thought is to not save a reference to the function directly, but maybe save the function name instead, and grab the function by name every time we want to call it.

If your classes are calling global functions with known names, then that pretty much solves your problem. No need to grab a reference in advance; it's not going to make a measurable performance difference. I think call_function supports passing the function name as a string anyway, right?


You typically store reference to a function value when the Lua script is registering a callback. In that case, it's much better than storing a name, because it allows the Lua script to register functions which are local, anonymous, ect.


If you really had to grab the value value in advance, as you're doing now (and there's really no reason to do that, but we'll pretend it's necessary), I would add a layer of indirection. You could have a LuaFunctionReference class which encapsulates a global name. During instantiation, it grabs a reference to the function the global contains. These objects could be acquired from a factory which maintains a list of all such references. When you reload a script, you could have the factory/manager/pool/etc. object iterate through the references and have them update themselves, so all the references tucked away in classes throughout the system would be updated.

Mud
  • 28,277
  • 11
  • 59
  • 92
  • Sure. Essentially what you're doing in your class is grabbing a reference to the function value referenced by a given name *at the time of class construction*. But what if the script author redefined that function during his script's execution? Your class won't pick up on the change in that case, either, it will reference the old function. For that reason alone, saving a reference to the function by value is not a good idea. – Mud May 04 '12 at 19:30
  • 1
    Yup. That means that the script author passes *you* the function he wants call, which eliminates both problems (the one in your OP and the one mentioned above). If you're doing the calling, then you're relying on the user to have stored a function value in a specifically named global. That means you should be retrieving that at the point of call, not in advance. What you're doing now really has no value other than as an optimization (preventing one global lookup), but it's a premature one because it will have no measurable impact and adds headaches that you're dealing with now. – Mud May 04 '12 at 19:35
  • Thanks again for your input. After considering your comments, I think what I'm going to do is store a single optional string per Entity, which refers to a table in Lua, which in turn contains functions, etc. I think this will be a good model because then I can take advantage of metatables and do more management on the Lua side if desired, yet the C++ side will still be decoupled and only know about it's string ID. – Raptormeat May 04 '12 at 19:53
  • You're pretty much doing that already, but it's implicit. You're referencing the global table, _G, and grabbing a value from it by it's string ID (that's what calling `call_function` with a name would do). Still, sticking the callbacks in a special table is probably better than forcing the script to pollute it's global namespace. I don't really know the context your doing this in, but in most cases I think it's cleaner to have the script register callbacks rather than the having the host call into the script based on naming convention. – Mud May 04 '12 at 20:02