daveg
daveg

Reputation: 1211

In Perl, why do I get "undefined subroutine" in a perl module but not in main ?

I'm getting an "undefined subroutine" for sub2 in the code below but not for sub1.

This is the perl script (try.pl)...

#!/usr/bin/env perl

use strict;
use IO::CaptureOutput qw(capture_exec_combined);

use FindBin qw($Bin);
use lib "$Bin";
use try_common;

print "Running try.pl\n";
sub1("echo \"in sub1\"");
sub2("echo \"in sub2\"");

exit;

sub sub1 {

(my $cmd) = @_;

print "Executing... \"${cmd}\"\n";
my ($stdouterr, $success, $exit_code) = capture_exec_combined($cmd);
print "${stdouterr}\n";

return;
}

This is try_common.pm...

#! /usr/bin/env perl

use strict;
use IO::CaptureOutput qw(capture_exec_combined);

package try_common;

use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
  sub2
);

sub sub2 {

    (my $cmd) = @_;

    print "Executing... \"${cmd}\"\n";
    my ($stdouterr, $success, $exit_code) = capture_exec_combined($cmd);
    print "${stdouterr}\n";

    return;
}

1;

When I run try.pl I get...

% ./try.pl
Running try.pl
Executing... "echo "in sub1""
in sub1

Executing... "echo "in sub2""
Undefined subroutine &try_common::capture_exec_combined called at 
/home/me/PERL/try_common.pm line 20.

This looks like some kind of scoping issue because if I cut/paste the "use IO::CaptureOutput qw(capture_exec_combined);" as the first line of sub2, it works. This is not necessary in the try.pl (it runs sub1 OK), but a problem in the perl module. Hmmmm....

Thanks in Advance for any help!

Upvotes: 0

Views: 9246

Answers (4)

brian d foy
brian d foy

Reputation: 132905

I hate when I make this mistake although I don't make it much anymore. There are two habits you can develop:

Most likely, make the entire file the package. The first lines will be the package statement and no other package statements show up in the file.

Or, use the new PACKAGE BLOCK syntax and put everything for that package inside the block. I do this for small classes that I might need only locally:

package Foo {
    # everything including use statements go in this block
    }

Upvotes: 0

Javier Elices
Javier Elices

Reputation: 2154

You should take a look at the perlmod document to understand how modules work. In short:

  1. When you use package A (in Perl 5), you change the namespace of the following code to A, and all global symbol (e.g. subroutine) definitions after that point will go into that package. Subroutines inside a scope need not be exported and may be used preceded by their scope name: A::function. This you seem to have found.

  2. Perl uses package as a way to create modules and split code in different files, but also as the basis for its object orientation features.

  3. Most of the times, modules are handled by a special core module called Exporter. See Exporter. This module uses some variables to know what to do, like @EXPORT, @EXPORT_OK or @ISA. The first defines the names that should be exported by default when you include the module with use Module. The second defines the names that may be exported (but need to be mentioned with use Module qw(name1 name2). The last tells in an object oriented fashion what your module is. If you don't care about object orientation, your module typically "is a" Exporter.

Also, as stated in another answer, when you define a module, the package module declaration should be the first thing to be in the file so anything after it will be under that scope.

Upvotes: 4

choroba
choroba

Reputation: 242198

You imported capture_exec_combined by the use clause before declaring the package, so it was imported into the main package, not the try_common. Move the package declaration further up.

Upvotes: 6

daveg
daveg

Reputation: 1211

I think I figured it out. If, in the perl module, I prefix the "capture_exec_combined" with "::", it works.

Still, why isn't this needed in the main, try.pl ?

Upvotes: -1

Related Questions