1

我正在评估 Ruby 中的脚本,我希望每个脚本都有自己的沙箱,并带有一个名为$window. 该$window变量应该指向不同的东西,具体取决于脚本在哪个沙箱中运行。线程局部变量可以工作,但我没有使用线程。我正在使用 Ruby C API,因此有点打开了可能性。

现在,我在 a 中运行每个脚本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

有什么方法可以关闭 a 中的全局变量Binding吗?我找到了一个可能的解决方案并将其发布在下面。

4

2 回答 2

1

不同的窗口将绑定到什么?

如果它们绑定到一个线程,那么解决问题的最简单方法是拥有一个线程局部变量,如果绑定到其他东西(比如说当前时间),那么你可能想要使用全局哈希。

我个人会选择一个专用的类,这将使以后更容易重构(您可能会重构它,因为全局变量是不良依赖注入的代码气味):

class Windows < Hash
end
WINDOWS = Windows.new
...
window_scope = WINDOWS[Time.now].binding

那么你有一个可变常量,它实际上是一个全局集合。

于 2012-12-21T10:54:10.590 回答
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;
}

它似乎有效,但我们会看看我是否遇到问题。

于 2012-12-24T18:44:49.843 回答