lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


OK, I admit, the globals / environments thing is really confusing. That script doesn't work, because getfenv(), getfenv(1), etc doesn't give me the environment of the calling thread; it always returns _G.  But the LUA_GLOBALSINDEX is different in each thread, because of a lua_setfenv call. 

Back to the drawing board.

(and sorry for the noise)

Graham

On May 13, 2008, at 9:47 AM, Graham Wakefield wrote:
That should be:

-- this wraps require to ensure that it is always called in the environment of the master state:
local oldrequire = require
local master = _G
function require(...)
-- cache the current calling environment:
local env = getfenv()
-- change to 'master' environment:
setfenv(0, master)
-- call the real require:
local ret = { oldrequire(...) }
-- restore to the current calling environment:
setfenv(0, env)
return unpack(ret)
end

On May 13, 2008, at 9:45 AM, Graham Wakefield wrote:
Yes, that's what I suspected. Tthe mapping of lua_setfenv, setfenv, LUA_GLOBALSINDEX and LUA_ENVIRONINDEX, for threads, userdata and C functions is quite confusing.

lfs = require "lfs" works, but some modules make other changes to the globals table besides returning themselves.

This works (run in the master state before any other scripts):

local oldrequire = requirelocal master = _Gfunction require(...) -- cache the current calling environment:
local env = getfenv() -- change to 'master' environment:
setfenv(0, master) -- call the real require:
oldrequire(...) -- restore to the current calling environment:
setfenv(0, env)end

On May 13, 2008, at 4:40 AM, Peter Cawley wrote:
Have you tried:
lfs = require "lfs"

Also, the Lua manual states:
" The thread environment (where global variables live) is always at
pseudo-index LUA_GLOBALSINDEX. The environment of the running C
function is always at pseudo-index LUA_ENVIRONINDEX."
Hence, setting a thread environment is the same as setting the thread
globals index. My guess is that LFS loaded its global table using the
globals index, so while the require function's environment index is
the globals table for the master state, because require was called
from a thead, using the globals index gives you the globals for that
thread, whereas if LFS loaded into the environment index, it would
load into (in this case) the master state globals.

My 2 cents.

2008/5/13 Graham Wakefield <lists@grahamwakefield.net>:
Hi,

 I have an application in which lua scripts may be loaded by the user. Each
script is given a 'child' lua_State created by lua_newthread(). Keeping each
table's variables separate is beneficial to the application, so the child
state is given a local environment, with a metatable __index to the master
globals, like this:

                lua_State *Ls = lua_newthread(L);

                // Create a local environment with a link to global
environment via __index metamethod
                // this means that script variables are not shared between
scripts
                lua_pushthread(Ls);
                        lua_newtable( Ls );
                                lua_pushvalue( Ls, -1 );
                                lua_setmetatable( Ls, -2 ); //Set itself as
metatable
                                lua_pushvalue( Ls, LUA_GLOBALSINDEX );
                                lua_setfield( Ls, -2, "__index" );
                        lua_setfenv( Ls, -2 );
                lua_pop(Ls, 1);

 A user script can load a module using require (e.g. require "lfs"), which
works as normal. However, if a second script is loaded, the global 'lfs' is
not accessible to the second script.

 script 1:

 require "lfs"
 print(lfs) -- table (0x....)

 script 2:

 require "lfs"
 print(lfs) -- nil
 print(package.loaded.lfs) -- table (0x...)

 I can't quite figure out why the second script doesn't get global access to
the module. I wonder if the require() call is pushing the module as a global
into script 1's environment, rather than the master state. Is this the case?
[in fact, does lua_setfenv() on a lua_State do the same as lua_replace(Ls,
LUA_GLOBALSINDEX)?]

 Is there a known workaround?

 Thanks,

 Graham


Be seeing you

grrr waaa
www.grahamwakefield.net


Be seeing you

grrr waaa
www.grahamwakefield.net


Be seeing you

grrr waaa
www.grahamwakefield.net