sanjay nayak has asked for the wisdom of the Perl Monks concerning the following question:


The code given below is well worked. But the problem is that the variable which is passed from the main program to the package P is only accessible within the sub routine sss. But what i want is that suggest me some technique so that the value of variable which i passes from the main program can be accessible within the module P(i.e it can accessible in any subroutines present inside that module).
#main.pl use strict; use Config::Tiny; use Config::P; my $DATA; open CONFIGFILE2, "imp1.txt" or die $!; { local $/; $/ = undef; $DATA=<CONFIGFILE2>; } print $DATA; # Create a config my $Config = Config::Tiny->new(); # Open the config, replace with read and $DATA with filename $Config = Config::Tiny->read_string( $DATA ); # see perldoc Config::Tiny my $s = $Config->{_}; #passing the variable $s to the module p P::sss($s); #package package p; use strict; my $s1; sub sss { $s1= shift; print $s1->{Local_IP};#it works fine } #out of sub routine it is not accesssible. print $s1->{Local_Port};#it doesn't work 1;
imp1.txt contains
Local_Port=5060
Local_IP = 127.0.0.1
  • Comment on How can i pass a variable from a program to a module so that it is accessible to the entire module.???
  • Download Code

Replies are listed 'Best First'.
Re: How can i pass a variable from a program to a module so that it is accessible to the entire module.???
by holli (Abbot) on Aug 24, 2006 at 13:14 UTC
    I stripped your code down to
    #main.pl use strict; use warnings; my $s = { Local_IP=>"127.0.0.1", Local_Port => 5060 }; #passing the variable $s to the module p P::sss($s); #package package P; use strict; my $s1; sub sss { $s1= shift; print $s1->{Local_IP}, "\n";#it works fine } #out of sub routine it is not accesssible. print $s1->{Local_Port}, "\n";#it doesn't work 1;
    and that happily prints
    127.0.0.1 5060
    so i think your datastructure doesn't contain what you think it does. Try dumping it with Data::Dumper. Also you don't need to read the config-file yourself. You can simply pass the filename to Config::Tiny:
    $Config = Config::Tiny->read( 'imp1.txt' );
    Oh, and I follow derby. The code is really messy.


    holli, /regexed monk/
Re: How can i pass a variable from a program to a module so that it is accessible to the entire module.???
by shmem (Chancellor) on Aug 24, 2006 at 14:39 UTC
    Sharing variables between packages doesn't work with lexical scoping (my variables, see e.g. Variable Scoping in Perl: the basics), but it is possible e.g using package globals.

    Generally it is a better idea to pass variable content to functions in other packages via function arguments, and to methods by e.g. binding them as attributes to an object of the foreign package. Sharing variables between packages can (or will) lead to confusion and should not be undertaken lightly.

    That said - you can declare a package global inside package P and set it from within the package main (default namespace):

    package P; use vars qw($f); sub foo { print "$f\n" } package main; $P::f = "howdy, world"; P::foo(); __END__ output: howdy, world

    You can also share variables between packages assinging to typeglobs in the respective symbol table (see e.g. Of Symbol Tables and Globs):

    package P; use strict; use vars qw($f); # NOTE: *f is a shared typeglob sub foo { print $f,"\n"; $f = "world"; } package main; use strict; use vars qw($f); # NOTE: *f shared with package P *P::f = *f; # make P::f an alias of main::f $f = "howdy"; P::foo(); # after this call, $f is changed! print $f,"\n"; __END__ ouput: howdy world

    You should use this approach only if you know well what you are doing, and state prominently in whatever file that uses a shared typeglob that it is doing so, and why you need it. The $main::f variable can be changed also in P assigning to $f, and it will be changed in main as well, which would give you some surprise if you aren't aware of it.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: How can i pass a variable from a program to a module so that it is accessible to the entire module.???
by wazzuteke (Hermit) on Aug 24, 2006 at 13:14 UTC
    The first thing I notice, and I will assume it was just a typo, is that you call P::sss( $s );, yet you package p;, which has a different name space than you expect. Again, I'll assume this was a typo.

    The second thing that pops out to me is the code execution flow. Let me step through it, and you may see what's happening:
    use P;
    The package P is compiled and code is executed (I will ignore use strict; module for simplistic sakes). In code execution/compile time it will:
    • Define $sl; lexically to the package. This is fine, though the variable has no value
    • Attempt to print $l->{'Local_Port'}.
    You may seee the issue here. Because the code gets compiled and executed at 'use' time, $sl really hasn't been defined yet, and will therefore not be the hash (or blessed hash) reference you expect it to be.

    Now, by then calling P::sss( $s ) the sss routine will then define $s1, print out the exepected contents and return out of the routine. Never again, however, will the print $1->{'Local_Port'} be executed.

    Overall, to get what you are looking for, you will have to find a way to define $sl before the first print. Without knowing more about the overall application, I would hate to direct you in the wrong direction. Nevertheless, I hope this helped out with your initial question.

    Good Luck!

    ha||ta
Re: How can i pass a variable from a program to a module so that it is accessible to the entire module.???
by derby (Abbot) on Aug 24, 2006 at 13:04 UTC

    Well ... the code above is a bit messy (mixing OO methods with module subroutines, package P vs Config::P). To answer the question, you need to export the symbol $s1.

    -derby

    Scratch that ... I didn't see *inside* the module. It is visibile inside the module ... but your not coding it correctly.

    Using just OO and not package subs, here's one way to do it:

    use strict; use warnings; use Config::Tiny; use MyConfig::P; my $DATA; open CONFIGFILE2, "imp1.txt" or die $!; { local $/; $/ = undef; $DATA=<CONFIGFILE2>; } close CONFIGFILE2; my $Config = Config::Tiny->new(); $Config = Config::Tiny->read_string( $DATA ); my $s = $Config->{_}; my $p = MyConfig::P->new( $s ); $p->sss(); $p->ppp();
    package MyConfig::P; sub new { my( $class, $val ) = @_; my $self = {}; $self->{config} = $val; bless $self, $class; } sub sss { my $self = shift; print $self->{config}{Local_IP}, "\n"; } sub ppp { my $self = shift; print $self->{config}{Local_Port}, "\n"; } 1;