I"m using LUA to extend a game engine. It's generally working OK (could wish for static type checking though...), but I've run into something I can't work out, and searching the list archives hasn't turned up an answer for any search I've tried so far.
The behavior I'm after seems like it should be very simple, maybe the most common thing to want, but I can't find a combination of metatable/setfenv behaviors to do it. I have a bunch of C++ internal game objects. Each of these C++ objects has a Lua table associated with it which defines a desired Lua global environment. All I want is to call a Lua fn from C++, and have this environment table be used for the Lua fn I call, and anything that *it* calls, recursively for the entire call stack. In other words, I
want my environment to be inherited.
I started out by trying to use setfenv on the Lua fn from C++ before I call it, pointing to my environment. For example, let's call this lua function LuaTest. I quickly discovered that the setfenv is not inherited through the call stack! I had to call setfenv in *every* Lua function called in the entire tree that LuaTest might call, which worked, but was not practical at all.
My second atttempt, and the one I have limping along now, was to define a metatable with __index and __newindex entries pointing to my desired environment for LuaTest, and setting this as the metatable for the module that contains LuaTest (*). This *almost* works. Every Lua fn called by LuaTest sees my environment table exactly as I wish but *only* within the module defining LuaTest. Once any function is called outside that module, my environment is
lost, replaced with the one defined by the setfenv of the called Lua function.
That's where I'm at now: I have the behavior I want but only within a single module. What I really wish is something that seems so very simple: I want the environment i set to be inherited by anything called by LuaTest. But I can't seem to get that behavior! I've tried some of the "pseudo-index" things too, but whatever I try, it seems some "function environment" always clobbers the real environment I'm trying to have inherited down through the Lua call stack.
Is there a nice simple way to do this?
For a while I was just setting a global "E" with my desired environment, and everybody had to say "E.myvar ...". That also works, even across modules, but it's a pain, and fragile: if anyone forgets to say "E.myvar", even just once, there's a bug. With the
metatable approach, at least I *know* variables are going into the environment I want them to.
Thanks!
(*) Actually I'm not using the Lua module system, but my own, but that's not related to my query above: I see the same troubles when using Lua's module system. Mine provides more private module behavior than the Lua module system, so you can say:
local my_module = Game.require('some/file.lua')
Your handle to it is private, and you can say my_module.some_function(). But I want some_function() to see the same Lua environment that its caller does!