打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Modify Lua Chunk Environment: Lua 5.2

It is my understanding that in Lua 5.2 that environments are stored in upvalues named _ENV. This has made it really confusing for me to modify the environment of a chunk before running it, but after loading it.

I would like to load a file with some functions and use the chunk to inject those functions into various environments. Example:

chunk = loadfile( "file" )-- Inject chunk's definitionschunk._ENV = someTable -- imaginary syntaxchunk( )chunk._ENV = someOtherTablechunk( )

Is this possible from within Lua? The only examples I can find of modifying this upvalue are with the C api (another example from C api), but I am trying to do this from within Lua. Is this possible?

Edit: I'm unsure of accepting answers using the debug library. The docs state that the functions may be slow. I'm doing this for efficiency so that entire chunks don't have to be parsed from strings (or a file, even worse) just to inject variable definitions into various environments.

Edit: Looks like this is impossible: Recreating setfenv() in Lua 5.2

Edit: I suppose the best way for me to do this is to bind a C function that can modify the environment. Though this is a much more annoying way of going about it.

Edit: I believe a more natural way to do this would be to load all chunks into separate environments. These can be "inherited" by any other environment by setting a metatable that refers to a global copy of a chunk. This does not require any upvalue modification post-load, but still allows for multiple environments with those function definitions.

asked Dec 23 '13 at 0:28
RandyGaul
1,418310


 
2  
Note that in the link you inserted, there's a comment by one of Lua authors –  akavel Dec 23 '13 at 1:06

 
I see the comment but I hardly know what he means. I don't have experience from 5.1 to understand. @akavel –  RandyGaul Dec 23 '13 at 1:21

 
uh, actually I'm also not 100% sure, but from what I understand, in practice this means roughly what you seem to have gotten from others already: that it's doable via debug lib or C API (and in fact, debug does use the C API), albeit made kinda difficult and nonobvious on purpose, so that it's not overused in regular day-to-day Lua code. And coming from lhf, the answer has high credibility and gives insight as to the original intent. –  akavel Dec 23 '13 at 9:28
add comment

2 Answers

up vote 3 down vote accepted

The simplest way to allow a chunk to be run in different environments is to make this explicit and have it receive an environment. Adding this line at the top of the chunk achieves this:

_ENV=...

Now you can call chunk(env1) and later chunk(env2) at your pleasure.

There, no debug magic with upvalues.

Although it will be clear if your chunk contains that line, you can add it at load time, by writing a suitable reader function that first sends that line and then the contents of the file.

answered Dec 23 '13 at 10:29
lhf
26.7k32142


 
Thanks a lot for the answer. It does seem quite nice, but adding that line to files is poor for scripting. So the comment about inserting this line just before reading a file is really cool. I am going to go try this out. –  RandyGaul Dec 23 '13 at 21:54
add comment

I do not understand why you want to avoid using the debug library, while you are happy to use a C function (neither is possible in a sandbox.)

It can be done using debug.upvaluejoin:

function newEnvForChunk(chunk, index)  local newEnv = {}  local function source() return newEnv end  debug.upvaluejoin(chunk, 1, source, 1)  if index then setmetatable(newEnv, {__index=index}) end  return newEnvend

Now load any chunk like this:

local myChunk = load "print(x)"

It will initially inherit the enclosing _ENV. Now give it a new one:

local newEnv = newEnvForChunk(myChunk, _ENV)

and insert a value for 'x':

newEnv.x = 99

Now when you run the chunk, it should see the value for x:

myChunk()

=> 99

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
lua5.2 改动(转)
通过hook实现类似反射功能
scons笔记
lua的调试器技术
20170128 长难句每日一句
Lua 5.1参考手册自译 【翻译】(】(LRM5.1-1)简介(1)、词法约定(2.1)、值与类型(2.2)、变量(2.3)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服