|
Okay, so my undestanding is WAY off.
Hmmm. I really don't know why my first approach didn't work then.
I don't know if some example lua code will be of any help, as I think it will be more down to how the environments are implemented and communicate with each other, which is all in c++.
This is a really really simple example.
------------------------------------------------------------
module code in Utilities.lua
module(..., package.seeall)
g_var = nil
-------------------------------------------------------
code from environment 1:
utils = require "Utilities"
utils.g_var = 1
print(utils.g_var)
-----------------------------------------------------
code from environment 2:
utils = require "Utilities"
print(utils.g_var)
------------------------------------------------------------
We know that the environment 1 code is called before environment 2, yet the results are the ouput is:
1
nil
This example is probably an massive oversimplification of the situation we are in. The environments are created like this:
static void CreateThread(State & state, State * host)
{
if (m_MainState == NULL)
{
m_MainState = luaL_newstate();
luaL_openlibs(m_MainState);
lua_sethook(m_MainState, lineHook, LUA_MASKLINE, 0);
// Create a table to store our references
lua_pushstring(m_MainState, "lookup");
lua_newtable(m_MainState);
// Make it a weak table so that references are removed automatically by the garbage collection
lua_pushstring(m_MainState, "__mode");
lua_pushstring(m_MainState, "v");
lua_settable(m_MainState, -3);
// Add this table as an entry in the globals table
lua_settable(m_MainState, LUA_GLOBALSINDEX);
}
lua_State * hostLuaState = host ? host->m_state : m_MainState;
// Create the new thread
state.m_state = lua_newthread(hostLuaState);
lua_pushvalue(hostLuaState, -1); // Prevent the new thread from being garbage collected
// Add to our list of registered states, keeping a reference to the state so we can remove it later on
m_RegisteredStates.push_back(ThreadRef(&state, hostLuaState, luaL_ref(hostLuaState, LUA_REGISTRYINDEX)));
// Create a local environment for this thread with a link to the global environment via __index metamethod
lua_newtable(hostLuaState);
lua_pushvalue(hostLuaState, -1);
lua_setmetatable(hostLuaState, -2); // Set itself as a metatable
lua_pushvalue(hostLuaState, LUA_GLOBALSINDEX);
lua_setfield(hostLuaState, -2, "__index");
lua_setfenv(hostLuaState, -2);
lua_pop(hostLuaState, 1);
By way of an explanation:
The State class is a wrapper for a lua_State *, and I pass in a host state so that we can have a heirarchy of environments and "inherit" a parents globals.
In the lua code example given, env 1 and env 2 would both inherit a common host environment, which itself is a child of the main state. i.e.
main->host->env 1
->env 2
(Apologies for the strange formatting of this email but we are having to use the MS Exchange Web client for our email at the moment!)
________________________________
From: lua-bounces@bazar2.conectiva.com.br [mailto:lua-bounces@bazar2.conectiva.com.br] On Behalf Of Duncan Cross
Sent: 01 August 2007 12:16
To: Lua list
Subject: Re: "Require" in a sandboxed environment
On 8/1/07, Tom Miles <Tom@creative-assembly.co.uk> wrote:
Now, my understanding of how modules work is that a module is loaded into a table, stored in a "packages" table, then a copy is also stored in the globals table of the enviornment it is loaded into, and another copy returned which can be stored in a differently named variable by the code calling require if desired. As lua doesn't work with references, if the module has a variable within it, then there will now by potentially 3 different copies of this variable.
Nope, Lua DOES use references, all three will be references to the same table. It sounds like there is must be some other problem if you are requiring packages from several environments created from the same original main state and they all seem to be getting a new version each time, the package system uses the shared registry table. Do you have a simple example of one of the modules you are using?
DISCLAIMER
This email is sent by The Creative
Assembly Limited company No. 03425917, registered in England & Wales
registered office 27 Great West Road, Middlesex, TW8 9BW, England. The contents
of this e-mail and any attachments are confidential to the intended recipient
and may also be legally privileged. Unless you are the named addressee (or
authorised to receive for the addressee) of this email you may not copy,
disclose or distribute it to anyone else. If you have received this email in
error, please notify us immediately by e-mail on postmaster@creative-assembly.co.uk
and then delete the email and any copies. The Creative Assembly Limited have
made all reasonable efforts to ensure that this e-mail and any attached
documents or software are free from software viruses, but it is the recipient's
responsibility to confirm this.