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

时间:2013-02-18 16:15:56

标签: c++ ruby

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

1 个答案:

答案 0 :(得分: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下次释放时被释放。