lua-users home
lua-l archive

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


在 2011年12月29日 上午11:25,While Loop <towlyhk-luageneral@yahoo.com.hk> 写道:
> Xavier Wang <weasley.wx <at> gmail.com> writes:
>> I'm wonder how to change _ENV's value, or rebuild a new _ENV locals in
>> C function. the only idea I make out is using a wrapping lua code:
>>
>> lua_newtable(L);
>> lua_pushcfunction(L, myfunc);
>> luaL_loadstring(L, "local _ENV,func = ... return func()");
>> lua_call(L, 2, 0);
>>
>> Is there any other method to change _ENV in a C function using a pure C API?
>
> I have no experience in writing C module. But I try to sum up a few points
> from the Lua 5.2 manual. If I am wrong someone please correct me.
> (1) C function no longer have environment.
>    LUA_ENVIRONINDEX and lua_getfenv are removed.
>
> (2) There is no _ENV for the C function itself. There is no way to change
>    _ENV variable of the caller lua function. You can only change things
>    inside the associated table.
>
> (3) C function do no inherit environment (and value/vars) from Lua function.
>    To access value/vars in the environment of the caller lua function,
>    pass the _ENV table or other variables to the C function as augement.
>
> (4) If the C function return a new function and you want to enclose some
>    values/vars in _ENV of the caller lua function to the new function.
>    You have to make a copy of those values/vars and associate them with
>    the new function by lua_pushcclosure or lua_setupvalue.
>
> But the description of lua_getupvalue/lua_setupvalue is not very clear.
>
> lua_getupvalue                  [-0, +(0|1), -]
> const char *lua_getupvalue (lua_State *L, int funcindex, int n);
> ... (Upvalues have no particular order, as they are active through the
> whole function. So, they are numbered in an arbitrary order.)
> ... For C functions, this function uses the empty string "" as a name for all upvalues.
>
> Upvalues have no name, and lua_getupvalue return them in arbitrary order !!??
> How to distinguish which value is which value ??
>
>
>
So, you mean, there is no way to write a C function like this in Lua ?

function change_env(t)
    local old_env = _ENV
    _ENV = t
   return old_env, t
end

I have looked into Lua5.2's module's implement, it has a C function
set_env, but this function only changed the value of the first upvalue
of current function. So if we call module in a function, not in a
file, it will be confused.

local module = module
local oldenv = _ENV
local newenv = {}
local _ENV = newenv
function mymod(...)
    module(...)
    function abc() end
    function def() end
end
_ENV = oldenv
package.preload.mymod = mymod
local m = require 'mymod'
assert(not m.abc and not m.def) -- abc and def not in m
assert(m == module) -- module function changed the first upvalue of
function mymod, that is module function itself.
assert(newenv.abc and newenv.def) -- abc and def are in newenv.