3

我有一个可以用 Ruby 扩展的应用程序。脚本可以在应用程序本身中创建,并在每次编辑时重新加载。因此,当用户向类添加方法时,它会立即生效。我不能只执行修改后的文件,就好像用户删除了一个方法,它应该不存在。唯一的选择是清除解释器的状态并重新加载所有脚本。但是 Ruby 会保护自己免受重启:( eval.c)

void ruby_init(void)
{
    int state = ruby_setup();
    if (state) {
        error_print();
        exit(EXIT_FAILURE);
    }
}

int ruby_setup(void)
{
    static int initialized = 0;
    int state;

    if (initialized)
        return 0;
    initialized = 1;

    /* ... */

    return state;
}

我还认为ruby_init()多次调用可能会导致 ruby​​ 跟踪并破坏 GC 的堆栈位置问题。重新启动整个应用程序不是一种选择,因为它具有 GUI 界面。将所有 ruby​​ 内容保存在一个单独的进程中也会很痛苦,因为在应用程序上插入新的 GUI 元素的 Qt 接口是暴露的。另一种选择是以某种方式跟踪所有已定义的方法、类、常量等,并在重新执行代码之前取消定义它们。有简单的方法吗?

4

1 回答 1

2

就在这里!(我认为)(这需要您使用一些 Ruby 代码来加载其他 Ruby 代码):

$current_env = nil

def reload(code)
  $current_env = Module.new
  $current_env.module_eval(code)
end

是的,就是这么简单。每当您需要从插件访问内容时,只需将 $current_env 作为模块访问:

$current_env::ExtensionClass.extension_thing

旧类在reload调用时被替换的东西变得不可访问,除了在下次 GC 时被释放。

于 2013-02-18T16:38:44.600 回答