我需要在tcl解释器中注册的每个命令之前调用一个代理函数(C / C ++)。对于临时命令,它很简单,我得到Tcl_CmdInfo
,记住它,并将我的代理函数设置为Tcl_CmdInfo
到objProc
字段。当我的代理被呼叫时,我会按照我的需要进行操作,然后从原始objProc
拨打Tcl_CmdInfo
。它运作正常。
问题是当我为他们调用info
时,整体命令(dict
,Tcl_SetCommandInfo
等)会停止为'整体'。它们工作正常,但不能被'namespace ensemble'修改。有什么想法吗?
PS。跟踪不是解决方案:它慢几倍,我不能接受它。
答案 0 :(得分:0)
执行此操作的官方API是跟踪。特别是,它禁用字节码编译,因此命令跟踪可以正确地用于字节码编译命令。是的,它的速度较慢,但这就是你准确跟踪到底发生了什么的结果。此外,你正在做的事情也将在Tcl 8.6中失败,因为它也有NRE(非递归执行引擎)实现的命令,并且那些不以任何有用的方式使用objProc
字段。我们正在考虑对未来版本的Tcl进行更大规模的修改(例如本机代码编译);你的拦截能力将进一步降低。
简而言之,你需要使用一种不同的方法,因为你要做的就是强烈反对现在运作良好的方法。例如,拦截由您控制的代码创建的所有过程或命令可能就足够了,而且开销会低得多。拦截过程的最简单方法是重写proc
命令:
rename proc my_real_proc
my_real_proc proc {name arguments body} {
set body "[list my_trace_hook $name];$body"
uplevel 1 [list my_real_proc $name $arguments $body]
}
然后,您可以通过任何您想要的机制,在my_trace_hook
中获取有关该过程的信息;它是从钩子程序内部调用的。它不会跟踪所有Tcl命令的作用,但添加该级别跟踪将始终对性能产生重大影响(仅将其添加到I / O命令中)。
如果不这样做,为什么要跟踪合奏本身呢?只需跟踪其中的子命令即可。 Tcl C API可以很容易地告诉您命令是否是一个集合,并提供其他内省选项。