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