February 2012
Intermediate to advanced
1184 pages
37h 17m
English
You can tie the same filehandle to both the input and the output of a
two-ended pipe. Suppose you wanted to run the
bc(1) (arbitrary precision calculator) program
this way:
use Tie::Open2;
tie *CALC, "Tie::Open2", "bc –l";
$sum = 2;
for (1 .. 7) {
print CALC "$sum * $sum\n";
$sum = <CALC>;
print "$_: $sum";
chomp $sum;
}
close CALC;One would expect it to print this:
1: 4 2: 16 3: 256 4: 65536 5: 4294967296 6: 18446744073709551616 7: 340282366920938463463374607431768211456
One’s expectations would be correct if one had the
bc(1) program on one’s computer, and one also
had Tie::Open2 defined as follows. This time we’ll use a blessed
array for our internal object. It contains our two actual
filehandles for reading and writing. (The dirty work of opening a
double-ended pipe is done by IPC::Open2; we’re just doing the fun
part.)
package Tie::Open2; use strict; use Carp; use Tie::Handle; # do not inherit from this! use IPC::Open2; sub TIEHANDLE { my ($class, @cmd) = @_; no warnings "once"; my @fhpair = \do { local(*RDR, *WTR) }; bless $_, "Tie::StdHandle" for @fhpair; bless(\@fhpair => $class)–>OPEN(@cmd) || die; return \@fhpair; } sub OPEN { my ($self, @cmd) = @_; $self–>CLOSE if grep {defined} @{ $self–>FILENO }; open2(@$self, @cmd); } sub FILENO { my $self = shift; [ map { fileno $self–>[$_] } 0,1 ]; } for my $outmeth ( qw(PRINT PRINTF WRITE) ) { no strict "refs"; *$outmeth = sub { my $self = shift; $self–>[1]–>$outmeth(@_); }; } for my $inmeth ( qw(READ READLINE GETC) ...Read now
Unlock full access