Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

How to access main package global vars in modules

by codewalker82 (Initiate)
on Jul 07, 2011 at 18:21 UTC ( [id://913237]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I have been searching the web for some advice on how to have persistent variables or how can we access a variable defined with our in a perl program file(.pl or main package one can say) across other modules.

I have read so many posts and articles but one or the other explains how to share global variables among packages( using exporter most of the time and somewhere through perl aliasing feature), but no one encounters a scenario in which a global variable from the main::package or say main.pl is required in some module.

To explain it or be specific in explaining my particular scenario let say:

#!/usr/bin/perl # main.pl use warnings; use strict; require "functions.pl"; our ($glbA, $glbB); $glbA = "Main_GlobalA"; $glbB = "Main_GlobalB"; procedureA(); procedureB();
#!usr/bin/perl # functions.pl use warnings; use strict; sub procedureA { print $glbA; } sub procedureB { print $glbB; } 1;
I have been stuck on this issue for a week now. Any sort of suggestion or correction in my approach would be of great help! Waiting for a prompt reply

Replies are listed 'Best First'.
Re: How to access main package global vars in modules
by philipbailey (Curate) on Jul 07, 2011 at 19:20 UTC

    There are several alternative one line changes that do what you ask, such as:

    • Declare $glbA and $glbB with our in functions.pl
    • Refer to those variables in functions.pl with the fully qualified $main::glbA and $main::glbB
    • no strict "vars"

    But none of the above is recommended. You would be much better in most scenarios to make functions.pl a package, and pass lexical variables as parameters to its functions.

Re: How to access main package global vars in modules
by ~~David~~ (Hermit) on Jul 07, 2011 at 19:22 UTC
    You need to fully qualify the variable:
    sub procedureA { print $main::glbA; } sub procedureB { print $main::glbB; }
Re: How to access main package global vars in modules
by GhodMode (Pilgrim) on Apr 02, 2012 at 14:23 UTC

    I had a very similar problem. This thread came up first in search resultes, but it didn't help me to understand the problem better. I'm sharing my experience here so that it may help the next person who finds this page in search results.

    The thread that helped me most is Variable Scoping in Perl: the basics

    The key is paying attention to the difference between the scope and the package. When you use my, it only declares a variable in the current scope, not in the current package. So, variables in a module that are declared with my in that module aren't accessible using the package name of the module, e.g. $main::var1.

    To declare variables in the current package and the current scope, use our.

    In my case, I wanted a global $logfile variable that I could reference in my module, but I wasn't able to access the main script's $logfile variable from the module's subroutine even if I used the fully-qualified name.

    The solution that worked best for me is to set $ModulePackage::logfile whenever I set the $logfile variable in the main script. I could have as easily declared the our $logfile in the main script, but then I would have had to use the fully-qualified name in the module.

    Also see package variable scope in module subroutine @ StackOverflow.

    --
    Ghodmode
    www.ghodmode.com
Re: How to access main package global vars in modules
by Anonymous Monk on Jul 08, 2011 at 12:21 UTC
    It's a good idea to put all globals, at least into a distinct package for "globals" which might not contain any executable code at all. You really do NOT want them "just lying around wherever you first thought to declare them." A program like that is extremely hard to maintain and harder yet to be kept reliable.
Re: How to access main package global vars in modules
by flexvault (Monsignor) on Jul 09, 2011 at 16:32 UTC

    I'm not sure that I understand your question, since in your example the use of globals should be very easy, but if you want to multi-fork(thread?) your package, then possible this will help. In Unix/Linux, I use this technique:

    #!/usr/local/bin/perl -w # Server.plx use warnings; use strict; our $root = "/usr/local"; # This should be a very protected location +! Different filesystem is even better our ( $GlobalLock, %HashA, @ArrayA . . . ); ## eval { require "functions.pl"; my $ret = Setup(0); ## Setup subroutine initializes the global va +riables only once ## I usually put the 'require's in the Setup +subroutine ## Then I can test with: perl -e 'require Ser +ver.plx; my $r = Setup(4);' ## Errors are now run-time errors the (4) is +debug level for logging. } if ( $@ ) { ## didn't work, you could retry or whatever } # fork childern while ( 1 ) { # check on children }

    And now the child activity after the fork.

    #!/usr/local/bin/perl -w # Server.plx ( really child after fork! ) use warnings; use strict; our $root; { ## $GlobalLock was opened by parent and is available to children for +processing ## Child is waiting for work ( in my case usually a socket wait ) ## If child needs to work on any global variables, should lock/unlock + with fork. ## And always check the return code from flock! }

    Obviously, a lot of code is needed to complete this sample, but the general idea is there. One thing that is critical, is to lock the globals when the children use them. For this, I use the $GlobalLock file and use flock to lock/unlock when ever I access a global variable.

    The global variables will remain in the parent address space, and may be used by the children. One strange thing that I have observed, is that after you check the syntax of your package ( perl -c -w server.plx ), sometimes I get run-time errors that many global can't be accessed from a subroutine. When I add 'our $root;' to the subroutine, all the run-time errors go away. You may have experienced this, and hence you question!

    This may be over-kill for your needs, but you're next step may be to add threads and work in parallel. Some one else on this list will have to coach you on what locking/unlocking requirements are needed for threads. A lot of programmers learn the hard way, myself included! You need to Lock it!

    Thank you and Good Luck

    "Well done is better than well said." - Benjamin Franklin

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://913237]
Approved by philipbailey
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2024-04-24 19:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found