static int
MyReplacementExit(ClientData unused, Tcl_Interp *interp, int argc, const char *argv[])
{
// Tcl_DeleteInterp(interp);
// Tcl_Finalize();
return TCL_OK;
}
int main() {
Tcl_Interp *interp = Tcl_CreateInterp();
Tcl_CreateCommand(interp, "exit", MyReplacementExit, NULL, NULL);
Tcl_Eval(interp, "exit ; puts 11111111");
std::cout << "22222222222" << std::endl;
return 0;
}
我需要处理tcl解释器的exit
命令评估。默认情况下,它会尝试删除自己,并调用关闭整个程序的std::exit
。这不是我想要的,所以我试图用自定义proc替换它。我不需要在退出处理程序proc中删除解释器(我可以在以后执行),只需要它在exit
命令后不继续评估命令。
在此代码中,我需要以某种方式更改MyReplacementExit
proc,因此11111111
不会被打印但是
22222222222
打印出来。
可以通过从TCL_ERROR
proc返回MyReplacementExit
来实现,但是我无法区分其他错误情况。
答案 0 :(得分:1)
替换exit
删除解释器(停止执行更多命令,但实际上不会立即删除数据结构,因为它仍然在使用中),重要,通过调用Tcl_Eval
和Tcl_Preserve
来打电话给Tcl_Release
。如果可以避免,请不要致电Tcl_Finalize
;那就是当你即将从内存中卸载Tcl库时,这可能非常棘手(坦率地说,退出流程更容易)。
以下是如何使用您的代码(改编):
static int
MyReplacementExit(ClientData unused, Tcl_Interp *interp, int argc, const char *argv[])
{
Tcl_DeleteInterp(interp); // <------------------
return TCL_OK;
}
int main() {
Tcl_Interp *interp = Tcl_CreateInterp();
Tcl_CreateCommand(interp, "exit", MyReplacementExit, NULL, NULL);
Tcl_Preserve(interp); // <------------------
Tcl_Eval(interp, "exit ; puts 11111111");
Tcl_Release(interp); // <------------------
std::cout << "22222222222" << std::endl;
return 0;
}
请注意,Tcl_Release
之后 ,因为它可能已被销毁(如同,内存已释放和在那一点上用随机的垃圾潦草地写下来。如果您需要检索结果并使用它们(例如,将它们打印出来),请事先这样做。
请注意,在这种特定情况下,您不需要保留/释放对;你的代码实际上并没有在Tcl_Eval
之后触及解释器(它在内部自己保存/释放)。
如果您不希望解释器终止,那就太麻烦了。 8.4中最干净的方法可能是抛出一个自定义异常代码(即任何大于TCL_CONTINUE
的代码),但不保证它可以用于任意代码,因为Tcl的catch
命令仍然可以捕获它。如果您真的处于这种情况,实际上更容易创建一个解释器,在子interp中运行任意代码,并在脚本结束时将其拆除;然后,您可以放弃该解释器而不会丢失太多上下文。的确,你可以做到:
Tcl_Preserve(interp);
if (Tcl_Eval(interp, theScriptToEval) != TCL_OK)
// Handle unexpected errors here
if (!Tcl_InterpDeleted(interp))
Tcl_DeleteInterp(interp);
Tcl_Release(interp);
是的,这意味着您希望将设置解释器的工作量保持在相当小的水平;你可能不想尝试在中断时每隔一毫秒调用一次......