重置嵌入式ruby解释器的状态

Reset state of embedded ruby interpreter

本文关键字:状态 解释器 ruby 嵌入式      更新时间:2023-10-16

我有一个可以用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接口是公开的。另一种选择是以某种方式跟踪所有定义的方法、类、常量等,并在重新执行代码之前取消它们的定义。有简单的方法吗?

是的,有!(我认为)(这需要使用一些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下次调用时会被释放。