Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Package fails because it refers to variable in main program - how to fix?

Reply
Thread Tools

Package fails because it refers to variable in main program - how to fix?

 
 
Henry Law
Guest
Posts: n/a
 
      06-24-2005
I have a main program and two packages. The first package loads up a
number of system-wide variables and exposes them to the program that
uses them. The second package has utility subroutines, some of which
need access to variables exposed by the first package. For example,
the log file name is a system-wide variable which is exposed as
"global" and in the "Utilities" package there's a routine that writes
log records.

I can't work out how to get the Utilities package to see the "global"
variables, despite reading perlmod fairly carefully; some pointers to
relevant bits of doc would be helpful.

This works, and shows that global variables are exposed:
----------------------------------------------------
#! C:\Perl\bin\Perl.exe

use strict;
use warnings;

use NFB::ClientGlobal(':all');
#use NFB::Utilities('logrec');

print "Log file name is $g_logfile\n";
----------------------------------------------------

F:\>tryit.pl
Log file name is F:\NFB\nfblog.txt

F:\>

I'm not going to paste in the whole of NFB::Utilities, but the key
lines are these:

sub logrec {
open (LOGFILE,">>main::$g_logfile") or die "etc..";

If I "use" it from the program above the error message is

Global symbol "$g_logfile" requires explicit package name at
NFB/Utilities.pm line 48.

In other words "logrec" is not seeing the definition of $g_logfile; as
you can see I have been experimenting with explicit package names -
including naming the "NFB::ClientGlobal" package that exposed the
$g_logfile variable in the first place, but all without success.
Coaching, please!
--

Henry Law <>< Manchester, England
 
Reply With Quote
 
 
 
 
Paul Lalli
Guest
Posts: n/a
 
      06-24-2005
Henry Law wrote:
> I have a main program and two packages. The first package loads up a
> number of system-wide variables and exposes them to the program that
> uses them. The second package has utility subroutines, some of which
> need access to variables exposed by the first package. For example,
> the log file name is a system-wide variable which is exposed as
> "global" and in the "Utilities" package there's a routine that writes
> log records.


This seems like a bad idea. If you have the ability to import from the
first package (as the main:: package does), why can't your second
package also import from it? Why does your second package need to
depend upon main:: having already imported from the first package?

> I can't work out how to get the Utilities package to see the "global"
> variables, despite reading perlmod fairly carefully; some pointers to
> relevant bits of doc would be helpful.
>
> This works, and shows that global variables are exposed:
> ----------------------------------------------------
> #! C:\Perl\bin\Perl.exe
>
> use strict;
> use warnings;
>
> use NFB::ClientGlobal(':all');
> #use NFB::Utilities('logrec');
>
> print "Log file name is $g_logfile\n";
> ----------------------------------------------------
>
> F:\>tryit.pl
> Log file name is F:\NFB\nfblog.txt


If I understand what you're saying, NFB::ClientGlobal declares a
package variable $g_logfile, and allows it to be exported. Your main
package then calls NFB::ClientGlobal->import(':all') (by way of the
'use' statement). This has the effect of allowing
$NFB::ClientGlobal::g_logfile to be used in package main:: without
fully declaring it.

Does that all sound correct?

If so, then it would seem to be the obvious solution for the second
package, NFB::Utilities, to also include a call to
use NFB::ClientGlobal qw/:all/;
so that $NFB::ClientGlobal::g_logfile can also be used by package
NFB::ClientGlobal.

> I'm not going to paste in the whole of NFB::Utilities, but the key
> lines are these:
>
> sub logrec {
> open (LOGFILE,">>main::$g_logfile") or die "etc..";
>
> If I "use" it from the program above the error message is
>
> Global symbol "$g_logfile" requires explicit package name at
> NFB/Utilities.pm line 48.


You haven't fully declared the global variable correctly. The sigil
($) goes before the package declaration, not the identifier name:

sub logrec {
open my $logfile, '>>', $main::g_logfile or die "etc...";
#...
}

> In other words "logrec" is not seeing the definition of $g_logfile; as
> you can see I have been experimenting with explicit package names -
> including naming the "NFB::ClientGlobal" package that exposed the
> $g_logfile variable in the first place, but all without success.
> Coaching, please!


Again, this method will "work", but is very buggy. A utility package
should never have to depend upon its caller having imported from
another package. If Package2 needs a variable exported by Package1,
Package2 should import Package1.

Hope this helps,
Paul Lalli

 
Reply With Quote
 
 
 
 
Anno Siegel
Guest
Posts: n/a
 
      06-24-2005
Henry Law <> wrote in comp.lang.perl.misc:
> I have a main program and two packages. The first package loads up a
> number of system-wide variables and exposes them to the program that
> uses them. The second package has utility subroutines, some of which
> need access to variables exposed by the first package. For example,
> the log file name is a system-wide variable which is exposed as
> "global" and in the "Utilities" package there's a routine that writes
> log records.


See how global variables mean trouble? Could you make the logfile a
parameter of the logrec() utility? It would have saved you this kind
of headache.

If it must stay global, Utilities should import it from ClientGlobal
on its own instead of relying on main:: to do it and making a cross-
package access. main:: can import it as well, if it needs to know.
That's the purpose of a configuration module like ClientGlobal that
whichever part of the program can consistently import what it needs
from it.

However, while roundabout, your method would work as well. You simply
haven't got the cross-package variable syntax right. See code correction
below.

> I can't work out how to get the Utilities package to see the "global"
> variables, despite reading perlmod fairly carefully; some pointers to
> relevant bits of doc would be helpful.
>
> This works, and shows that global variables are exposed:
> ----------------------------------------------------
> #! C:\Perl\bin\Perl.exe
>
> use strict;
> use warnings;
>
> use NFB::ClientGlobal(':all');
> #use NFB::Utilities('logrec');
>
> print "Log file name is $g_logfile\n";
> ----------------------------------------------------
>
> F:\>tryit.pl
> Log file name is F:\NFB\nfblog.txt
>
> F:\>
>
> I'm not going to paste in the whole of NFB::Utilities, but the key
> lines are these:
>
> sub logrec {
> open (LOGFILE,">>main::$g_logfile") or die "etc..";


It's $main::g_logfile, not main::$g_logfile. That's all that is wrong.

[snip rest of code]

Anno
 
Reply With Quote
 
Henry Law
Guest
Posts: n/a
 
      06-24-2005
On 24 Jun 2005 17:44:47 GMT, (Anno
Siegel) wrote:

>Henry Law <> wrote in comp.lang.perl.misc:
>> I have a main program and two packages. The first package loads up a
>> number of system-wide variables and exposes them to the program that
>> uses them. The second package has utility subroutines, some of which
>> need access to variables exposed by the first package.


>If it must stay global, Utilities should import it from ClientGlobal
>on its own instead of relying on main:: to do it and making a cross-
>package access. main:: can import it as well, if it needs to know.
>That's the purpose of a configuration module like ClientGlobal that
>whichever part of the program can consistently import what it needs
>from it.


Thanks, Paul and Anno. There is a reason why I'm trying to do what
I'm doing but the faint whiff of not-right-ness has now become a foul
reek so I fear I can't avoid some re-structuring.

But before I crawl back to my editor, advise me once more: the
routines I'm writing make quite intensive use of a small set of
system-wide variables - the host name of the server, for example, the
name of the database to connect to, the name of the log file, etc etc.
I'm as against global variables as the next guy (learnt that in APL
programming way back last century) but what is the most convenient way
of making them accessible when they're needed?
--

Henry Law <>< Manchester, England
 
Reply With Quote
 
Tad McClellan
Guest
Posts: n/a
 
      06-24-2005
Henry Law <> wrote:
> On 24 Jun 2005 17:44:47 GMT, (Anno
> Siegel) wrote:



[ snip using a bunch of global "configuration" variables ]


> Thanks, Paul and Anno. There is a reason why I'm trying to do what
> I'm doing but the faint whiff of not-right-ness has now become a foul
> reek so I fear I can't avoid some re-structuring.
>
> But before I crawl back to my editor, advise me once more: the
> routines I'm writing make quite intensive use of a small set of
> system-wide variables - the host name of the server, for example, the
> name of the database to connect to, the name of the log file, etc etc.
> I'm as against global variables as the next guy (learnt that in APL
> programming way back last century) but what is the most convenient way
> of making them accessible when they're needed?



Package (global) variables live in the Symbol Table, which is just
a hash with some special access methods.

Simply use your own hash instead of the symbol table hash:

$cf{server} = '127.0.0.1'; # instead of $server
$cf{db_name} = 'myDatabase; # instead of $db_name
...

ie. have 1 global hash with 27 keys rather than 27 separate globals.


--
Tad McClellan SGML consulting
Perl programming
Fort Worth, Texas
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
How do I call function that a variable refers to? yaru22 Javascript 5 09-02-2006 04:14 PM
Compilation fails when a windows form user control is assigned a strong name but it refers to an activex control which does not have strong name ashish_gokhale ASP .Net Web Controls 0 05-05-2005 01:38 PM
i see a lot of refers Karnev Computer Support 16 10-01-2003 09:31 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57