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!