lua-users home
lua-l archive

Re: Lua registry, environment, and threads.

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


2010年1月6日 Christian Tellefsen <christian.tellefsen@funcom.com>:
> Hi,
>
> I have a question about the Lua registry, environment, and threads. I have
> the following code:
>
> int Test(lua_State * L )
> {
> lua_getglobal(L, "print");
> lua_getglobal(L, "a");
> lua_pcall(L, 1, 0, 0);
>
> return 0;
> }
>
> int main (void) {
> int error;
> lua_State * L = lua_open(); /* opens Lua */
> luaL_openlibs(L);
>
> lua_pushnumber(L, 0); // In the global environment, a = 0
> lua_setglobal(L, "a");
>
> // Create a thread with its own environment.
> lua_State * L1 = lua_newthread(L);
>
> lua_pushthread(L1); // thread
> lua_newtable(L1); // thread, t
> lua_pushvalue(L1, LUA_GLOBALSINDEX); // thread, t, _G
> lua_setfield(L1, -2, "__index"); // thread, t
> lua_pushvalue(L1, -1); // thread, t, t
> lua_setmetatable(L1, -2); // thread, t
> lua_setfenv(L1, -2); // thread
>
> lua_pushnumber(L1, 1); // In the thread environment, a = 1
> lua_setglobal(L1, "a");
>
> lua_pop(L1, 1); // -
>
> // Put the C function in the registry, and retrieve it and call it from the
> root and the child thread.
> lua_pushcfunction(L, &Test);
> int r0 = luaL_ref(L, LUA_REGISTRYINDEX);
>
> lua_rawgeti(L, LUA_REGISTRYINDEX, r0);
> lua_pcall(L, 0, 0, 0);
>
> lua_rawgeti(L1, LUA_REGISTRYINDEX, r0);
> lua_pcall(L1, 0, 0, 0);
>
> // Load the buffer and store it in registry, and retrieve it and call it
> from the root and the child thread.
> const char * txt = "print(a)";
> luaL_loadbuffer(L, txt, strlen(txt), "x");
>
> int r1 = luaL_ref(L, LUA_REGISTRYINDEX);
>
> lua_rawgeti(L, LUA_REGISTRYINDEX, r1);
> lua_pcall(L, 0, 0, 0);
>
> lua_rawgeti(L1, LUA_REGISTRYINDEX, r1);
> lua_pcall(L1, 0, 0, 0);
> }
>
> This prints:
>
> 0
> 1
> 0
> 0
>
> So, as far as I can tell, the C function will print out the 'a' in the
> thread's environment, but the identical Lua function loaded through
> luaL_loadbuffer() will always print out the 'a' in the global environment.
>
> Does anyone know why this gives a different result? And is there any way I
> can get the second case to work in the same way as the first one, that is,
> print the 'a' in the thread's environment?
At any point in a Lua function (be it implemented in C or Lua), you
have three possible environments: the function environment
(LUA_ENVIRONINDEX), the thread environment (LUA_GLOBALSINDEX), and the
interpreter environment (LUA_REGISTRYINDEX).
Functions implemented in Lua use the function environment when
accessing globals (and you have to use the debug library to access the
other ones).
Functions implemented in C can choose which one to use. The
lua_getglobal macro uses LUA_GLOBALSINDEX, which is accessing the
thread environment rather than the function environment, and which is
kind of misleading since it doesn't mimick the behavior of global
variables in Lua code.

AltStyle によって変換されたページ (->オリジナル) /