Reputation: 3262
I have a perl module module.pm
and a script.pl
file which calls the module.pm
is it possible that module.pm
knows about files declared inside script.pl
for example :
I have a file defination under script.pl
something like this
use module;
open FILE,'>','file.txt' or die 'can\'t open file';
inide module.pm i want to use FILE handle for example :
package module
print FILE $value;
is it possible to do something like this and, if yes, how ?
Upvotes: 1
Views: 835
Reputation: 51157
As Flimzy answers, you should not do this. There are better ways to accomplish whatever it is you're trying to accomplish. I'll cover some in a second.
You can open a file in a different namespace than your package—or print to one:
package module;
print main::FILE "some text\n";
alternatively, in your program:
open(module::FILE, '>', '/tmp/file');
You could use caller
to find the caller's package (instead of just assuming main). That way, you could always use the caller's FILE.
You really should be using globs stored in scalars nowadays. In other words, your open call should look like this:
open my $file, '>', '/tmp/file'
Then $file
is an ordinary scalar, and you can pass it around like you would any other variable. So, maybe you'd have this code in your module:
package module;
sub foo {
my $dest = shift;
print $dest "hello, world\n";
}
1;
And then in your program, after that open, you'd call module::foo($file)
.
If you have a bunch of routines in module that all take the same output filehandle, it can get tedious to pass it around all the time. Instead, create an object:
package module;
use Moose;
has output_fh => (
is => 'rw',
required => 1,
);
sub foo {
my $self = shift;
print $self->output_fh "hello, world\n";
}
Then, in your non-module code, you do something like this:
open my $fh, … ;
my $obj = module->new(output_fh => $fh);
$obj->foo();
the advantage of this approach grows as you start to carry around more state in $obj
.
If you don't want to go the OO approach (which is generally cleaner than this approach) you can do this in your module:
package module;
our $OUTPUT_FH = undef; # or sensible default
sub foo {
print $OUTPUT_FH "hello, world\n";
}
and then in your non-module code:
open my $fh, … ;
local $module::OUTPUT_FH = $fh;
module::foo();
The local
-ization will make sure that when your current block exits, the previous value of $module::OUTPUT_FH
is restored. This will make subroutine calls work (without trampling each other's settings) as long as each subroutine that changes it localizes it first.
Perl 5.6 (released 2000-03-22, almost 12 years ago) introduced filehandle autovivification that makes that open my $fh, …
line work. In earlier versions, you need to make the glob yourself. The Symbol
module provides an easy way:
use Symbol qw(gensym ungensym);
my $fh = gensym; # not sure if pre-5.6 had geniosym; if so, use that instead
open $fh, …
⋮
close $fh;
ungensym $fh;
If you want to go before perl 5, which became stable in 1995, then you're on your own.
Upvotes: 3
Reputation: 13646
If you use lexical filehandles instead of Barewords it is possible.
use module ;
open( my $filehandle , '>' , 'output.txt' ) or die 'Cannot open.' ;
module::some_fun( $filehandle ) ;
and in module.pm
package module ;
sub some_fun {
my ( $filehandle ) = @_ ;
print $filehandle "Hello world.\n" ;
}
1 ;
Hope that helps.
Upvotes: 5
Reputation: 79604
It may be possible to do this if you don't use strict
, but it's really bad practice. The better option is to pass the file handle to your module.pm
method/function(s).
use module;
open my $FILE,'>','file.txt' or die 'can\'t open file';
somesub($FILE);
Then:
package module;
sub somesub {
my $FILE = shift;
...
}
Upvotes: 3