A problem with storing a filehandle as an instance variable

A problem with storing a filehandle as an instance variable

am 21.12.2007 02:53:20 von 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.

Re: A problem with storing a filehandle as an instance variable

am 21.12.2007 06:25:04 von krahnj

Sniff wrote:
>
> 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
--
use Perl;
program
fulfillment

Re: A problem with storing a filehandle as an instance variable

am 21.12.2007 17:41:59 von Ben Morrow

Quoth "John W. Krahn" :

>
> 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

Re: A problem with storing a filehandle as an instance variable

am 21.12.2007 18:22:15 von Peter Makholm

Ben Morrow writes:

> Quoth "John W. Krahn" :
>
>>
>> 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.

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

Re: A problem with storing a filehandle as an instance variable

am 21.12.2007 20:21:41 von 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

Re: A problem with storing a filehandle as an instance variable

am 21.12.2007 20:24:17 von Sniff

On Dec 21, 11:21=A0am, Sniff wrote:
> Well, I'm learning more than I ever wanted to about Perl Filehandles
> and typeglob :-). =A0I hacked at it last night and final got it to work
> by doing this:
>
> in contructor:
> =A0 =A0my $fhw =3D *wr{FILEHANDLE};
> =A0 =A0$self->{"WRITE"} =3D $fhw;
>
> in my method:
> =A0 =A0local(*WRITE);
> =A0 =A0*WRITE  = $self->{"WRITE"};
> =A0 =A0print *WRITE "$flag\n" ;

TYPO: Should be
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

Re: A problem with storing a filehandle as an instance variable

am 21.12.2007 21:56:57 von Uri Guttman

>>>>> "S" == Sniff writes:

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

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org