Multiple package with exporter in Perl - perl

I'm trying to get familiar with Perl exporter, the issue i am facing is whatever I try I cannot use exporter with modules containing multiple packages in it. What am I missing below?
MyModule.pm
use strict;
use warnings;
package Multipackage1;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(test1);
sub test1 {
print "First package\n";
}
1;
package Multipackage2;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(test2);
sub test2 {
print "Second package\n";
}
1;
package Multipackage3;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT_OK = qw(test3);
sub test3 {
print "Third package\n";
}
1;
MyMainFile.pl
#!/usr/bin/perl
use strict;
use warnings;
use Multipackage;
use Multipackage qw(test3);
print "Calling first package:\n";
test1();
print "Calling second package:\n";
test2();
print "Calling third package:\n";
test3();
I getting test1 is not part of the main package.
Thanks in advance.

The use calls require, which looks for a file with the package name (with / for :: and + .pm).
So require the actual file with packages instead and then import from packages.
main.pl
use warnings;
use strict;
require MyModule;
import Multipackage1;
import Multipackage2;
import Multipackage3 qw(test3);
print "Calling first package:\n";
test1();
print "Calling second package:\n";
test2();
print "Calling third package:\n";
test3();
In the MyModule.pm, place each package in its own block to provide scope for lexical variables, since package doesn't do that, or use package Pack { ... } since v5.14. There is no need for all those 1s, and you may pull use Exporter; out of the blocks.
Output
Calling first package:
First package
Calling second package:
Second package
Calling third package:
Third package
Better yet, replace our #ISA = qw(Exporter); with use Exporter qw(import); for
use strict;
use warnings;
package Multipackage1 {
use Exporter qw(import);
our #EXPORT = qw(test1);
sub test1 { print "First package\n" }
}
...
1;
with the same output.
Note that putting multiple packages in one file is normally not needed and not done.

Related

Import symbols from package defined in the same file

I hoped I could do something like this:
p.pl :
package Common;
use strict;
use warnings;
use experimental qw(signatures);
use Exporter qw(import);
our #EXPORT = qw(NA);
sub NA() { "NA" }
package Main;
use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures);
Common->import();
say "Main: ", NA();
my $client = Client->new();
$client->run();
package Client;
use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures);
Common->import();
sub run($self) {
say "Client: ", NA();
}
sub new( $class, %args ) { bless \%args, $class }
to share common symbols between two packages in the same file. However running this script gives:
$ perl p.pl
Main: NA
Undefined subroutine &Client::NA called at ./p.pl line 30.
What am I missing here?
The problem is that you call
$client->run();
before
Common->import();
A simple way to inline modules:
BEGIN {
package Common;
use strict;
use warnings;
use experimental qw(signatures);
use Exporter qw(import);
our #EXPORT = qw(NA);
sub NA() { "NA" }
$INC{"Common.pm"} = 1;
}
Then you can use use Common; as normal.
It's not perfect. Hooking into #INC like App::FatPacker does provides the best results. But it will make your life easier.

Can't use Exporter properly

I've wasted many days on a larger block of code, containing Exporter statements, which used to work about a year ago. Several variations on this have failed, including an install of ./FOO/BAR/Foobar.pm which signaled success.
I am using Windows 10, Perl v5.26.0, built for MSWin32-x64-multi-thread
Caller.pl
#!/usr/bin/perl
use lib ".";
use lib "./FOO/BAR";
use strict;
use warnings;
use FOO::BAR::Foobar;
print "try FOO::BAR::Foobar::foo()\n";
FOO::BAR::Foobar::foo(); # perl can't find this
print "try foo()\n";
foo(); # errors out - can't find &main::foo
print "done\n";
./FOO/BAR/Foobar.pl
#!/usr/bin/perl -w
use strict;
use warnings;
package Foobar;
our($VERSION , #ISA , #EXPORT , #EXPORT_OK , %EXPORT_TAGS , $FOO);
BEGIN {
require Exporter;
#ISA = qw(Exporter);
#EXPORT_OK = qw(foo);
}
sub foo {
print "Loaded\n";
$FOO = q{some val};
}
1;
Execution dump
perl Caller.pl
try FOO::BAR::Foobar::foo()
Undefined subroutine &FOO::BAR::Foobar::foo called at Caller.pl line 12.
What's going on? Should I abandon any use of Exporter? But then how to link functions across modules?
There are three things going wrong:
With FOO::BAR::Foobar::foo(): There is no such sub, there is only Foobar::foo().
With foo(): use FOO::BAR::Foobar; is the equivalent of BEGIN { require FOO::BAR::Foobar; FOO::BAR::Foobar->import() }, but there is no method import available in the package FOO::BAR::Foobar, since you're inheriting Exporter into the package Foobar.
With foo(): You're using #EXPORT_OK instead of #EXPORT, which means that you need to explicitly import foo, but you're not doing that in use FOO::BAR::Foobar;.
So two things are needed to fix this:
As already pointed out in the comment by #HåkonHægland, change package Foobar; to package FOO::BAR::Foobar;.
Change use FOO::BAR::Foobar; to use FOO::BAR::Foobar qw/foo/;.
Then the code you've shown will work - there's no need to abandon Exporter. I'd just recommend a different style of using Exporter: Instead of inheriting via #ISA, just import import into your package. Here's how I would have written your file ./FOO/BAR/Foobar.pm:
package FOO::BAR::Foobar;
use strict;
use warnings;
use Exporter 'import';
our #EXPORT_OK = qw(foo);
our $FOO;
sub foo {
print "Loaded\n";
$FOO = q{some val};
}
1;

Perl: script and module calling a second module

I have the following:
Module1
package module1;
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(<list of subs within>);
use Module2;
sub M1S1 ()
{
$x = M2S1();
}
Module 2
package module2;
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(<list of modules within>);
sub M2S1()
{
...
}
sub M2S2()
{
...
}
Script
use Module2;
use Module1;
$y = M1S1();
$z = M2S2();
When the script calls a sub in Module 1 which in turn calls a sub in Module 2, the sub is not found, even though the script can call those subs directly.
I'm not a beginner to Perl by any means, but I've never fully gotten the hang of modules. Our environment has gotten very dependent on module2, so I don't want to make any changes that would require changing all the scripts that use it. Module1 has limited use so I can make changes to it if necessary.
The file name, the name in the package directive, and the name in the use statement must match, and that includes case.
Module1.pm
package Module1;
use Module1;
Or if you had a non-flat namespace,
Foo/Bar.pm
package Foo::Bar;
use Foo::Bar;
Note that you can have similar problems when you have two exporting modules that use each other (directly or indirectly), but that doesn't seem to the case.
$ cat Module1.pm
package Module1;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT = qw( M1S1 );
use Module2;
sub M1S1 { M2S1() }
1;
$ cat Module2.pm
package Module2;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT = qw( M2S1 M2S2 );
sub M2S1 { "M2S1" }
sub M2S2 { "M2S2" }
1;
$ cat script.pl
#!/usr/bin/perl
use strict;
use warnings;
use Module2;
use Module1;
print(M1S1(), "\n");
print(M2S2(), "\n");
$ ./script.pl
M2S1
M2S2

how to export names when package name is different from file name?

I have a file Scanners.pm which contains 2 packages. I want both these packages to export some names. I do not want those packages be in separate files, I want them to be in one file.
When I write
package SCAN;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(#SCANNERS #NAMES %NAMES name_index process_scanners);
our #EXPORT_OK = qw();
and then in the calling .pl file
use Scanner;
the names in the #EXPORT list are not exported. How I do that?
You can create a custom import sub for your Scanner package. Exporting Without Using Exporter's import Method.
Note, this code only will work if the user relies on the default #EXPORT only. If you want them to be able to specify what functions they want, then you'll have to filter before calling export_to_level.
package Scanner;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(scannersub);
use strict;
use warnings;
sub import {
Scanner->export_to_level(1, #_);
ScannerTwo->export_to_level(1, #_);
}
sub scannersub {
print "scanner->sub says hi\n";
}
package ScannerTwo;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(scannertwosub);
sub scannertwosub {
print "scannertwo->sub says hi\n";
}
1;
__END__
and your script
use Scanner;
use strict;
use warnings;
scannersub();
scannertwosub();
1;
__END__
Finally, I would be remis if I didn't mention that this isn't a great idea on it's surface. Future maintainers of this code will not easily be able to trace these subs. So whatever your reason for wanting them in the same file but different packages, I suspect there is a better solution.

Why don't functions from package A get imported into package B when they recursively call each other?

I'm trying to use two packages and call functions from one to other, but I've got this error:
Undefined subroutine &module2::method_1_2 called at module2.pm line 20.
Is there any way to call functions from one package to the other one without getting this error?
Thanks in advance.
xabi
exec error:
./test.pl
method_1_1
method_2_1
method_2_2
Undefined subroutine &module2::method_1_2 called at module2.pm line 20.
Sample code (test.pl):
#!/usr/bin/perl
use strict;
use module1;
use module2;
method_1_1();
method_2_2();
module1.pm
package module1;
use strict;
use module2;
require Exporter;
use vars qw(#ISA #EXPORT);
#ISA = qw(Exporter);
#EXPORT = qw( method_1_1 method_1_2 );
sub method_1_1
{
print "method_1_1\n";
method_2_1();
}
sub method_1_2
{
print "method_1_2\n";
}
1;
module2.pm:
package module2;
use strict;
use module1;
require Exporter;
use vars qw(#ISA #EXPORT);
#ISA = qw(Exporter);
#EXPORT = qw( method_2_1 method_2_2 );
sub method_2_1
{
print "method_2_1\n";
}
sub method_2_2
{
print "method_2_2\n";
method_1_2();
}
1;
The problem is that the very first thing module1 does is to use module2. That means all of module2 is read and executed while module1 is still compiling.
The next thing to happen is that module2 does use module1. Because module1 has been found and put into %INC Perl doesn't execute it again, and just does module1->import to fetch the exported symbols.
But of course module1 has in fact barely started compiling, and #module1::EXPORT doesn't even exist, never mind about its two subroutines. That makes Exporter import nothing at all into module2, so when it comes to make the call method_1_2() it knows nothing about it.
The cleanest way to fix this is to do the import after the compilation (including all the use statements and BEGIN blocks) but before runtime. Perl's INIT block is ideal for this, and we can get the code working by changing the modules to the form below. I have shown only module2 here, as the pattern of calls means this is all that's needed to fix this particular problem, but the general case needs the equivalent change to all cooperating modules.
package module2;
use strict;
use warnings;
use module1;
INIT { module1->import }
use base 'Exporter';
our #EXPORT = qw( method_2_1 method_2_2 );
sub method_2_1 {
print "method_2_1\n";
}
sub method_2_2 {
print "method_2_2\n";
method_1_2();
}
1;
The problem is that you assign to #EXPORT after it was already used. The following is copied from Mini-Tutorial: Mutual Use of Exporting Modules
[ The need to use this technique is a very strong indicator of a design flaw in your system, but I recognize that the resources are not always available to fix design flaws. ]
If ModA uses ModB, ModB uses ModA, and ModA or ModB imports symbols from the other, one needs to pay attention to code execution order. The best way I've found to avoid problems is to setup Exporter before loading any other module.
# ModA.pm
package ModA;
use strict;
use warnings;
use Exporter qw( import );
BEGIN { our #EXPORT_OK = qw( ... ); }
use This;
use ModB;
use That;
...
1;
# ModB.pm
package ModB;
use strict;
use warnings;
use Exporter qw( import );
BEGIN { our #EXPORT_OK = qw( ... ); }
use This;
use ModA;
use That;
...
1;
Interesting, I am not sure why method_1_2 isn't being exported into the module2 namespace, but you can get around this by explicitly referencing the package:
module1.pm
package module1;
use strict;
use warnings;
use module2 (); #don't import methods
use base 'Exporter';
our #EXPORT = qw( method_1_1 method_1_2 );
sub method_1_1
{
print "method_1_1\n";
module2::method_2_1();
}
sub method_1_2
{
print "method_1_2\n";
}
1;
module2.pm
package module2;
use strict;
use warnings;
use module1 (); #don't import methods
use base 'Exporter';
our #EXPORT = qw( method_2_1 method_2_2 );
sub method_2_1
{
print "method_2_1\n";
}
sub method_2_2
{
print "method_2_2\n";
module1::method_1_2();
}
1;
Okay, I think I see what is going on, but take this with a grain of salt. The use function is effectively a BEGIN block and BEGIN blocks run as soon as they are parsed, so the code looks like this in execution order.
perl starts parsing test.pl
it sees use module1; so it loads module1.pm and starts parsing it
perl sees use module2; in module1.pm so it loads module2.pm and starts parsing it
At this point, the functions in module1 do not yet exist, so they can't be imported
parsing continues
Something Borodin said tipped me off to the best solution: "#module1::EXPORT doesn't even exist". The problem here is that the #EXPORT variable doesn't exist. This can be fixed by putting it in a BEGIN block:
module1.pm
package module1;
use strict;
use warnings;
use base 'Exporter';
BEGIN {
our #EXPORT = qw( method_1_1 method_1_2 );
}
use module2;
sub method_1_1
{
print "method_1_1\n";
module2::method_2_1();
}
sub method_1_2
{
print "method_1_2\n";
}
1;
module2.pm
package module2;
use strict;
use warnings;
use base 'Exporter';
BEGIN {
our #EXPORT = qw( method_2_1 method_2_2 );
}
use module1;
sub method_2_1
{
print "method_2_1\n";
}
sub method_2_2
{
print "method_2_2\n";
method_1_2();
}
1;
IMPORTANT NOTE: I do not believe prototypes in module1 will be honored in any of these cases (and I don't see how they could be since module2 gets compiled before module1, so it can't know the prototypes exist). This is yet another argument to never use prototypes.