Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can perl modules "use" other perl modules?

Tags:

perl

perl 5.24.0 on linux

Perl module "nesting" (sort of) problem... I can't seem to get this to work and was wondering if someone could tell me what's wrong. The simple example below will articulate my problem better than my verbage...

First, ping.pl...

#!/usr/bin/env perl
# This is ping.pl

use ping_mod;

ping_dbh();

exit;

Next up is the perl module, ping_mod.pm...

#!/usr/bin/env perl
use Exporter;
use ping_common;

package ping_mod;

@ISA = qw(Exporter);
@EXPORT = qw(ping_dbh);

sub ping_dbh {
    set_dbh();
    print "dbh = $dbh\n";
}

1;

Finally is ping_common.pm which ping_mod uses...

#!/usr/bin/env perl
use Exporter;

our $dbh;

package ping_common;

@ISA = qw(Exporter);
@EXPORT = qw($dbh set_dbh);

sub set_dbh {
    $dbh = 99;
}

1;

When I run ping.pl, I get...

Undefined subroutine &ping_mod::set_dbh called at ping_mod.pm line 11.

But if I change ping_mod.pm to be...

#!/usr/bin/env perl
use Exporter;
use ping_common;

package ping_mod;

@ISA = qw(Exporter);
@EXPORT = qw(ping_dbh);

sub ping_dbh {
#    set_dbh();
#    print "dbh = $dbh\n";
    print "hi there\n";    
}

1;

... it runs fine. So, I'm thinking it must be exporting OK. But "useing" ping_common messes it up somehow.

Even if I "use ping_common" in ping.pl, it still can't find it.

like image 402
daveg Avatar asked Jan 26 '23 04:01

daveg


1 Answers

As @toolic said, use ping_common has to be after the package statement. Here's why.

Packages in Perl isolate global variables and functions. The full name for ping_dbh is really ping_mod::ping_dbh. You can call ping_dbh in the ping_mod package. If you want to call it elsewhere you must use its full name, ping_mod::ping_dbh.

use Module is really require Module to load it and Module->import to import its functions and variables into the current package. It doesn't matter where the module is loaded, so long as it is loaded. But it is very important where it is imported.

With this in mind, look at this.

use ping_common;

package ping_mod;

That will load ping_common and import its functions, not into ping_mod, but into the default package main. They will not be available to ping_mod.

package ping_mod;

use ping_common;

This also loads ping_common, but it imports its functions into ping_mod.

But why does Exporter still work, even outside the package?

use Exporter;
use ping_common;

package ping_mod;

@ISA = qw(Exporter);
@EXPORT = qw(ping_dbh);

Ironically, Exporter does not work by exporting. It works by inheritance. @ISA = qw(Exporter); makes ping_mod inherit the import method from Exporter. That @ISA, because it is in the ping_mod package, is the global variable @ping_mod::ISA.


.pm files should generally start with a package statement. They should not start with a #!; though it doesn't hurt anything. #! tells the operating system what to use to run the file as an executable program. Perl modules are generally not executables.

You can read more about packages in perlmod.

like image 186
Schwern Avatar answered Jan 30 '23 07:01

Schwern