Why doesn't my Perl script use my module? - perl

module.pm
package module;
use 5.012;
use warnings;
sub Parse
{
return 1;
}
1;
script.pl
#!/usr/bin/perl -w
use 5.012;
use warnings;
use lib 'C:/';
use module;
print Parse("value");
Stdout
Undefined subroutine &main::Parse

You need either to write:
print module::Parse("value");
or to change the module package to export the name Parse.
See http://perldoc.perl.org/perlmod.html#Perl-Modules for guidance in exporting symbols from your module.
(By the way, you should really name your module Module rather than module. Lowercase module-names are used for Perl built-in features like use warnings and use strict.)

Several things:
First, use Local as your module prefix. That way, if you just happen to have a module with the same name in your Perl installation, it will use yours. Call it "Local::Module". Then, create a Local directory, and name your module Module.pm.
The other thing you have to understand is that you define your module in another namespace. By default, everything is in the main namespace until you use the package statement. That creates another namespace that your package uses. This way, if your package has a function foo, and you've defined a function foo in your main program, they won't collide.
Thus, you have two choices: One (the preferred now) is to simply call your subroutine with the full package name prepended to it. The second is to export your subroutine names to your main program. This can cause problems with duplicate names, but you don't have to keep typing in the package name every time you call your subroutine.
Without Exporting the name
Local/Module.pm
# /usr/bin/env perl
# Local/Module.pm
package Local::Module;
use strict;
use warnings;
sub Parse {
my $value = shift; #Might as well get it.
print "I got a value of $value\n";
return $value;
}
1; #Need this or the module won't load
program.pl
# /usr/bin/env perl
# program.pl
use strict;
use warnings;
use Local::Module;
Local::Module::Parse("Foo");
With export:
Local/Module.pm
# /usr/bin/env perl
# Local/Module.pm
package Local::Module;
use strict;
use warnings;
use Exporter qw(import);
our #EXPORT_OK(Parse); #Allows you to export this name into your main program
sub Parse {
my $value = shift; #Might as well get it.
print "I got a value of $value\n";
return $value;
}
1; #Need this or the module won't load
program.pl
# /usr/bin/env perl
# program.pl
use strict;
use warnings;
use Local::Module qw(Parse);
Parse("Foo");

Related

Undefined subroutine &main::key_enc

I have a Perl module named McuEnc.pm which is located at /home/eric/temp directory:
package McuEnc;
use 5.010;
use strict;
use warnings;
use Exporter qw(import);
our #EXPORT_OK = qw(key_enc data_enc data_dec);
sub key_enc { some code }
sub data_enc { some code }
sub data_dec { some code }
1;
I have a Perl script named test.pl which is also located at /home/eric/temp directory:
use 5.010;
use strict;
use warnings;
use McuEnc qw(key_enc data_enc data_dec);
key_enc("1111");
...
I have changed working directory to /home/eric/temp. Now if I run test.pl script, it runs correctly. But if I create a new directory /home/eric/temp/My and move the McuEnc.pm file into it and then modify the test.pl script as follwoing:
use 5.010;
use strict;
use warnings;
use My::McuEnc qw(key_enc data_enc data_dec);
key_enc("1111");
...
then I'm getting the following error when I run test.pl again:
Undefined subroutine &main::key_enc called at ./test line 6.
However, I can still call the subroutine correctly with:
McuEnc::key_enc("1111");
So why I'm getting the error message? what is wrong?
This was answered by Sobrique in the comments, but it was never posted as an official answer:
"The use statement doesn't match the package statement. Try package My::McuEnc instead"

Wrong way of exporting perl functions from a module

I have a very small module and I am having trouble with exporting the functions from it.
Take the function GetVar() if I call it using TestMod::GetVar() It will work fine, however when I call GetVar() from the script in which the module is imported I get an error (listed below). I am 99% sure that I have not exported the function GetVar() correctly, however I can not find my mistake.
Module source:
#!/usr/bin/perl
use strict;
package TestMod;
our (#ISA, #EXPORT, $VERSION);
use Exporter;
#ISA = qw(Exporter);
#EXPORT = qw(&GetVar);
$VERSION = 0.01;
sub GetVar()
{
return "something";
}
1;
Script source:
#!/usr/bin/perl
use strict;
use lib "/home/user1221/projects/";
use module;
print "Version: $TestMod::VERSION";
my $a = GetVar(); #should work but doesn't
print "$a\n";
Error:
Undefined subroutine &main::GetVar called at /home/user1221/projects/module_use.pl line 8.
use module; in your script is exact equivalent of
BEGIN { require module; module->import(); }
but since you don't have module package nothing is imported.
What you need is
BEGIN { require module; TestMod->import(); }
or make sure your module file names follow package names.

BEGIN blocks in Perl

Searching the Internet, I get that the BEGIN block will get evaluated and executed in the compile phase. But can the #INC or other variables be inherited?
Below is what I wrote for testing. The directory structure is as:
|-- alexpackages
| |-- alex1.pm
| `-- alex2.pm
|-- foo.pl
`-- main.pl
For each file:
cat alexpackages/alex1.pm
package alex1;
sub foo()
{
print "this is alex1::foo\n";
}
1;
cat alexpackages/alex2.pm
package alex2;
sub foo2()
{
print "this is is alex2::foo2\n";
}
1;
cat foo.pl
alex1::foo();
cat main.pl
BEGIN
{
push(#INC, '~/programs/perl/alexpackages');
}
use strict;
use warnings;
use alex1;
use alex2;
#alex1::foo(); # 1. This works good
system("perl foo.pl"); # 2. This fails
Just as what my program tells that the #INC does not work for a new system call. It seems to me that system call will not inherit the system environment. Am I right?
And can how I make the environment variables to the following system call?
Processes started with system will inherit the environment variables from the calling process, but #INC is just a global Perl variable, not a system environment variable. It is not visible outside the Perl program.
A couple of notes on your code
Package names, being globals, should be capitalised, so your packages should be Alex1 and Alex2, in files alexpackages/Alex1.pm and alexpackages/Alex2.pm
It is best to use the lib pragma to manipulate #INC, so
use lib '~/programs/perl/alexpackages'
is best. And a use statement creates an implicit BEGIN block, so that is also unnecessary.
It is wrong to use prototypes on Perl subroutines, so sub foo() should be just sub foo
You may prefer to use Exporter to copy the symbols of a package into the calling code. That way you don't have to fully-qualify your subroutine name when you call it, like foo() instead of Alex1::foo()
The code would look like this
main.pl
use strict;
use warnings;
use lib '~/programs/perl/alexpackages';
use Alex1;
foo();
~/programs/perl/alexpackages/Alex1.pm
package Alex1;
use strict;
use warnings;
use base 'Exporter';
our #EXPORT = qw/ foo /;
sub foo {
print "This is Alex1::foo\n";
}
1;
There are many ways to specify library search directories both from within a Perl script or the command line. Here are two things you could do to make another directory available to the Perl script you invoke with system:
$ENV{PERL5LIB} = "~/programs/perl/alexpackages";
system("perl foo.pl");
system("perl -I~/programs/perl/alexpackages foo.pl");
Both PERL5LIB and the -I switch are documented in perlrun.

Perl subroutine naming conflicts

How does Perl resolve subroutine naming conflicts when parsing modules in the #INC path?
I'm writing a Perl module and I don't want my subroutine names to conflict with anything that already exists.
This should shed some light here.
Test script
#!/usr/bin/perl
use warnings;
use strict;
# import 'print_stuff' from TestPackage
# so you can call this sub without package name
use TestPackage qw(print_stuff);
my $string = "whatever";
TestPackage::print_stuff($string);
print_stuff($string);
sub print_stuff {
my $str = shift;
print "test.pl: $str\n";
}
Test package
package TestPackage;
# Export subs, which will enable you to call these
# subs without package name(TestPackage)
require Exporter;
#ISA = qw(Exporter);
#EXPORT_OK = qw(print_stuff);
sub print_stuff {
my $str = shift;
print "TestPackage: $str\n";
}
1;
Output:
$ test.pl
TestPackage: whatever
test.pl: whatever
Use package to build separate namespaces in modules, so you can avoid this kind of problems. The package statement declares the compilation unit as being in the given namespace. This link may helps you.

Perl problem 'require' the same file

I have a shared module in perl. The main program needs two files, first, a shared file (let's call it 'X'), and, second, a 'package' file. File 'X' is also included in the 'package' file using 'require'. When I compile this program it gives me the following error:
Undefined subroutine &main::trim called at testing.pl line 8.
My understanding is that perl couldn't find the trim() module. If I don't include the package file, then this will run without any problem.
Can anyone shed light on this problem?
These are my codes:
Main program: testing.pl
#!/usr/bin/perl -w
use strict;
use postgres;
require "shared.pl";
trim("als");
Package File: postgres.pm
#!/usr/bin/perl
package postgres;
use strict;
use DBI;
require "shared.pl";
1;
shared file: shared.pl
#!/usr/bin/perl
# =============
# shared module
# =============
use strict;
sub trim($)
{
}
1;
If the module doesn't use package, you want do instead of require. See What is the difference between library files and modules?.
do "shared.pl" or die $#;
You really should create a proper module, one with a package statement.
package Shared;
use strict;
use warnings;
our #EXPORT = qw( trim );
use Exporter qw( import );
sub trim { ... }
1;
Name the file Shared.pm and load it using use Shared;.
By default, require will only load a file one time. In this case, that one time is from the file postgres.pm, in the postgres package. So the trim subroutine gets defined in the postgres namespace as &postgres::trim.
One workaround would be to use the fully qualified subroutine name in the testing.pl file:
postgres::trim("als"); # not trim("als")
Another workaround is to hack the %INC table (the variable that keeps track of what modules/files have already been use'd and require'd) so you can reload shared.pl into the main package:
use postgres;
delete $INC{"shared.pl"};
require "shared.pl";
A third workaround would be to export the trim function from the postgres package to the main package. The docs for the Exporter module are a good introduction to why and how this is done.
# in postgres.pm
*main::trim = *trim;
# or in testing.pl
*trim = *postgres::trim;
trim("als");