How to pass filehandle as reference between modules and subs in perl -


i'm maintaining old perl code , need enable strict pragma in modules. have problem in passing file handle reference between modules , subs. have common module responsible opening log file passed typeglob reference. in other modules, run function first calls open_log() common module, passes file handle other subs.

here i've written simple test simulate situation.

#!/usr/bin/perl -w use strict;  $::status_ok = 0; $::status_not_ok = 1;  sub print_header {   our $file_handle = @_;    print { $$file_handle } "#### header ####"; # reference passing fails }  sub print_text {   ($file_handle, $text)= @_;    print_header(\$file_handle);   print { $$file_handle } $text; }  sub open_file_handle {   ($file_handle, $path, $name) = @_;    $filename = $path."\\".$name;   unless ( open ($$file_handle, ">".$filename)) {     print stderr "failed open file_handle $filename writing.\n";     return $::status_not_ok;   }   print stderr "file $filename opened writing successfully.\n";   return $::status_ok; }  $gpath = "c:\\temp"; $gname = "mylogfile.log"; $gfile_handle;  if (open_file_handle(\$gfile_handle, $gpath, $gname) == $::status_ok) {   $text = "big success!!!\n";   print_text(\$gfile_handle, $text);   print stderr $text; } else {   print stderr "epic fail!!!!!!!!\n"; } 

the main function first calls open_file_handle , passes file handle reference print_text function. if comment out row:

print_header(\$file_handle); 

everything works fine, need pass file handle reference other functions print_text function, , doesn't work.

i'm java developer , perl's reference handling not familiar me. don't want change open_log() sub return file handle (now returns status), since have lots of modules , hundreds of code lines go through make change in places.

how can fix code make work?

there 2 types of filehandles in perl. lexical , global bareword filehandles:

open $fh, '>', '/path/to/file' or die $!; open filehandle, '>', '/path/to/file' or die $!; 

you dealing first, good. second 1 global , should not used.

the file handles have lexical, , stored in scalar variable. it's called scalar because has dollar sign $. these can passed arguments subs.

foo($fh); 

they can referenced. in case, scalar reference.

my $ref = \$fh; 

usually reference stuff if hand on function perl not make copy of data. think of reference pointer in c. it's memory location of data (structure). piece of data remains is.

now, in code have references these scalars. can tell because dereferenced in print statement saying $$fh.

sub print_text {   ($file_handle, $text)= @_;    print_header(\$file_handle);   print { $$file_handle } $text; } 

so $file_handle parameter (that's = @_ does) reference. not need reference again when pass function.

i guess wrote print_header yourself:

sub print_header {   our $file_handle = @_;    print { $$file_handle } "#### header ####"; # reference passing fails } 

there few things here: - our globals. not use that. use my instead. - put parenthesis around parameter assignment: my ($fh) = @_ - since pass on reference reference scalar, need dereference twice: ${ ${ $file_handle } }

of course double-deref weird. rid of passing variable $file_hanlde print_header instead of refence it:

sub print_text {   ($file_handle, $text)= @_;    print_header($file_handle); # <-- no backslash here   print { $$file_handle } $text; } 

that need to make work.

in general, rid of references $file_handle vars here. don't need them. lexical filehandle reference io::handle object, don't concern right now, not important. remember:

  • use filehandles have $ front
  • pass them without references , not need worry \ , ${} , stuff that

for more info, see perlref , perlreftut.


Comments

Popular posts from this blog

c# - DetailsView in ASP.Net - How to add another column on the side/add a control in each row? -

javascript - firefox memory leak -

Trying to import CSV file to a SQL Server database using asp.net and c# - can't find what I'm missing -