Wed Jul 19, 2006, [CMcC]: A quickie to serialise the variables in a sub-[interpreter]. This has undoubtedly already been done, but I can't recall where it is. ---- '''nstree''' returns a flattened trees of all namespaces in the interp. proc nstree {interp {prefix ""}} { set result {} foreach ns [$interp eval [list namespace children $prefix]] { lappend result $ns lappend result {*}[nstree $interp $ns] } return $result } '''serialize''' returns a valid tcl command to recreate the variables in the interp. proc serialize {interp} { $interp eval {unset -nocomplain errorCode; unset -nocomplain errorInfo} set result {} foreach v [$interp eval info globals] { if {[string match tcl* $v]} continue if {[$interp eval [list array exists $v]]} { lappend result [list array set $v [$interp eval [list array get $v]]] } else { lappend result [list set $v [$interp eval [list set $v]]] } } foreach ns [nstree $interp] { set subresult {} foreach v [$interp eval [list info vars ${ns}::*]] { if {[array exists $v]} { lappend subresult [list array set [namespace tail $v] [$interp eval [list array get $v]]] } else { lappend subresult [list set [namespace tail $v] [$interp eval [list set $v]]] } } lappend result [list namespace eval $ns [join $subresult {; }]] } return [join $result "; "] } ---- [Zarutian] 14. okt 2008: There is one proplem with this. The sub interp ''knows'' that it is being serialized. [Lars H]: Yes, that's typical of Tcl; information isn't hidden, we just trust our programs to not poke their noses where they aren't supposed to be. I suppose if you really don't trust the interpreter you want to serialise, the you'll just have to [interp hide] all the sensitive commands and replace them with suitable aliases, like so: foreach cmd {namespace unset info array set} { interp hide $interp $cmd interp alias $interp $cmd {} $interp invokehidden $cmd } This way, even if the slave interp has tried to "patch" e.g. [unset] in an attempt to detect the initial unsettings of [errorCode] and [errorInfo], it will only patch the alias, so '''serialize''' still has unhindered access. There are however two holes in these precausions: * [info] is a [namespace ensemble], so what we really need to hide is the component commands ::tcl::info::globals and ::tcl::info::vars. This, in turn, runs into the problem that [interp hide] only works for global commands, so first we'd have to [rename] them… * The primary way to discover that something is being done to variables is not to patch [set] or the like, but to set a [trace] on the variable. Getting around that mechanism is trickier (it's probably easiest to remove all traces on a variable before serialising it, and then put them back). The code above also had several quoting errors regarding variable names (assuming that [[set $v]] and [[eval set $v]] always did the same thing), but I think I have corrected these. ---- Related concepts: [interp], [serializing] ---- [AM] (15 june 2010) While invoking procedures in another interpreter is easy, [exchanging variables between interpreters] requires a bit of trickery. ---- !!!!!! %| [Category Example] |% !!!!!!