我正在使用Ruby评估脚本,我希望每个脚本都有自己的沙箱,其中包含一个名为$window
的全局变量。 $window
变量应该根据脚本运行的沙箱指向不同的东西。线程局部变量可以工作,但我不使用线程。我正在使用Ruby C API,因此可以开启一些可能性。
现在,我在Binding
内运行每个脚本,因此它们在那里有点沙盒。绑定可以具有闭合的局部变量,但不能具有全局变量。这是个主意:
sandbox1 = window1.get_binding
sandbox2 = window2.get_binding
sandbox3 = window3.get_binding
sandbox1.eval('$window.foo') # calls 'foo' on window 1
sandbox2.eval('$window.foo') # calls 'foo' on window 2
sandbox3.eval('$window.foo') # calls 'foo' on window 3
有没有办法在Binding
内关闭全局变量?我找到了一个可能的解决方案并将其发布在下面。
答案 0 :(得分:1)
不同的窗户会绑在什么位置?
如果他们被绑定到一个线程,那么解决问题的最简单方法就是拥有一个Thread local variable,如果绑定到其他东西(让我们说当前时间),那么你可能想要使用一个全局哈希。
我个人会去一个专门的类,这将使以后更容易重构(你可能会重构这个,因为全局变量是代码注入差的依赖注释的代码味道):
class Windows < Hash
end
WINDOWS = Windows.new
...
window_scope = WINDOWS[Time.now].binding
然后你有一个可变常量,它实际上是一个全局集合。
答案 1 :(得分:0)
我找到了使用Ruby C API的可能解决方案。在绑定中评估的任何内容都将位于该绑定的调用框架下。使用Ruby 1.8.7,我可以在C:
中完成public VALUE getCurrentWindow()
{
// Get the current call frame from Ruby.
FRAME* frame = ruby_frame;
// Traverse up the call frame stack until we find a Window class.
while (frame) {
if (RTEST(rb_obj_is_kind_of(frame->self, rb_cWindow))
return frame->self;
frame = frame->prev;
}
// Couldn't find the window.
return Qnil;
}
它似乎有用,但我们会看到是否遇到问题。