A problem with storing a filehandle as an instance variable

S

Sniff

I have been working with Perl for a few months now and in my latest
program I decided to give Perl OO a try. :)

In an object I'm trying to use a Filehandle (or Glob) which is uses to
communicate with a child. I have been trying to keep these handles in
an instance variable but it doesn't seem to work. I have tried a few
different ways but I think I'm having issues dereferencing the
variables.

Here are some of the ways I have tried to do this:

In my class constructor I do this:

my $fhw = *write{FILEHANDLE};
$self->{"WRITE"} = $fhw;
# ... repeated for READ, ERROR ...
# Then I call open3 with those 3 handles
open3( $self->{"WRITE"}, $self->{"READ"}, $self->{"ERROR"},
"worker.pl" );

Later in a method I tried :

print $self->{"WRITE"} "$someMessage\n" ; # this creates a syntax
error, why?

I also tried this:
In the class constructor:
$self->{"WRITE"} = \*WRITE; #using a reference to a globtype
#later on I call open3 as I did above
Then in a method I tried :
print {$self->{"WRITE"}} "$message\n" ; #No error but I don't
think it worked

My first version of all this code was written in non-OO style and it
works fine, but I was using a bareword (i.e. *WRITE) for the file
handles. Any help would be appreciated.
 
J

John W. Krahn

Sniff said:
I have been working with Perl for a few months now and in my latest
program I decided to give Perl OO a try. :)

In an object I'm trying to use a Filehandle (or Glob) which is uses to
communicate with a child. I have been trying to keep these handles in
an instance variable but it doesn't seem to work. I have tried a few
different ways but I think I'm having issues dereferencing the
variables.

Here are some of the ways I have tried to do this:

In my class constructor I do this:

my $fhw = *write{FILEHANDLE};

*write{FILEHANDLE} is the 'FILEHANDLE' (or 'IO') slot in the symbol
table of the 'write' package variable so are we to assume that you used
open( write, ">filename" ) to create the filehandle?

$self->{"WRITE"} = $fhw;

You need to assign a reference to the filehandle typeglob:

$self->{ WRITE } = \*write;

# ... repeated for READ, ERROR ...
# Then I call open3 with those 3 handles
open3( $self->{"WRITE"}, $self->{"READ"}, $self->{"ERROR"},
"worker.pl" );

Later in a method I tried :

print $self->{"WRITE"} "$someMessage\n" ; # this creates a syntax
error, why?

perldoc -f print
[ SNIP ]
Note that if you're storing FILEHANDLEs in an array, or
if you're using any other expression more complex than a
scalar variable to retrieve it, you will have to use a
block returning the filehandle value instead:

print { $files[$i] } "stuff\n";
print { $OK ? STDOUT : STDERR } "stuff\n";

So you have to write that as:

print { $self->{ WRITE } } "$someMessage\n";

I also tried this:
In the class constructor:
$self->{"WRITE"} = \*WRITE; #using a reference to a globtype

Here you use WRITE in upper case. So is the filehandle write or WRITE?

#later on I call open3 as I did above
Then in a method I tried :
print {$self->{"WRITE"}} "$message\n" ; #No error but I don't
think it worked

My first version of all this code was written in non-OO style and it
works fine, but I was using a bareword (i.e. *WRITE) for the file
handles.

*WRITE is a typeglob, WRITE is a bareword.


It is probably better to just use lexical variables for filehandles:

open my $fhw, '>', 'filename' or die "... $!";

$self->{ WRITE } = $fhw;


perldoc -f open
perldoc perlopentut


John
 
B

Ben Morrow

Quoth "John W. Krahn said:
It is probably better to just use lexical variables for filehandles:

Unfortunately this doesn't work with open3, which is what the OP was
using.

Ben
 
P

Peter Makholm

Ben Morrow said:
Unfortunately this doesn't work with open3, which is what the OP was
using.

Lexical variables does work with open3 and it even shown in the
documentation, except that you have to do some magic to get the error
filhandle to work:

use Symbol;
my ($in, $out, $err);
# Generate filehandle for $err so it's not false:
$err = gensym;

my $pid = open3($in,$out,$err,'cmd');

//Makholm
 
S

Sniff

Well, I'm learning more than I ever wanted to about Perl Filehandles
and typeglob :). I hacked at it last night and final got it to work
by doing this:

in contructor:
my $fhw = *wr{FILEHANDLE};
$self->{"WRITE"} = $fhw;

in my method:
local(*WRITE);
*WRITE = $self->{"WRITE"};
print *WRITE "$flag\n" ;

Now I'm going to take some time to absorb the info you gave me above
and incorporate that knowledge into how I'm using the handles.

Thanks to John, Ben and Makholm
 
S

Sniff

Well, I'm learning more than I ever wanted to about Perl Filehandles
and typeglob :).  I hacked at it last night and final got it to work
by doing this:

in contructor:
   my $fhw = *wr{FILEHANDLE};
   $self->{"WRITE"} = $fhw;

in my method:
   local(*WRITE);
   *WRITE  = $self->{"WRITE"};
   print *WRITE "$flag\n" ;

TYPO: Should be
print WRITE "$flag\n" ;
 
U

Uri Guttman

S> Well, I'm learning more than I ever wanted to about Perl Filehandles
S> and typeglob :). I hacked at it last night and final got it to work
S> by doing this:

S> in contructor:
S> my $fhw = *wr{FILEHANDLE};

stop doing that! that is not doing what you think it does. it gets the
handle slot of a glob, but NOT a handle. there is NO REASON for you to
use that syntax to get a handle.

you can use IO::Handle or Symbol::gensym to get new handles. or use open
with a undefined lexical. but STOP using the above construct!

S> in my method:
S> local(*WRITE);
S> *WRITE = $self->{"WRITE"};

use a lexcial to hold handles. globs (even localized) are very old
fashioned.

my $wr = IO::Handle->new() ;

or
open( my $wr, '>', $file ) or die "can't create $file" ;

S> print *WRITE "$flag\n" ;

S> Now I'm going to take some time to absorb the info you gave me above
S> and incorporate that knowledge into how I'm using the handles.

better to forget what you know about globs and learn about lexicals and
handles.

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top