stdout redirection

If you are using Tcl 8.6, you can trap all the output to stdout by adding a suitable transform via chan push:

# Use a class to simplify the capture code
oo::class create CapturingTransform {
    variable var
    constructor {varName} {
        # Make an alias from the instance variable to the global variable
        my eval [list upvar \#0 $varName var]
    }
    method initialize {handle mode} {
        if {$mode ne "write"} {error "can't handle reading"}
        return {finalize initialize write}
    }
    method finalize {handle} {
        # Do nothing, but mandatory that it exists
    }

    method write {handle bytes} {
        append var $bytes
        # Return the empty string, as we are swallowing the bytes
        return ""
    }
}

# Attach an instance of the capturing transform
set myBuffer ""
chan push stdout [CapturingTransform new myBuffer]

# ... call the problem code as normal ...

# Detach to return things to normal
chan pop stdout

Things to note: this captures all output on the channel, however produced (it even works across threads or where the output is generated at the C level), and this puts bytes into myBuffer as the capturing is applied after the conversion to the channel’s configured encoding. And it requires 8.6; the API concerned wasn’t exposed to scripts in earlier versions (though it’s C-equivalent was used by some extensions for things such as SSL support).

Leave a Comment