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

I am trying to use two packages and call functions from one to the other, but I have this error:

Undefined routine & module2 :: method_1_2, called on module2.pm line 20.

Is there a way to call functions from one package to another 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; 
+4
source share
3 answers

The problem is that the very first module1 is use module2 . This means that all module2 read and executed while module1 is still compiling.

The next thing that happens is that module2 does use module1 . Since module1 was found and placed in %INC , Perl does not execute it again and simply executes module1->import to retrieve the exported characters.

But, of course, module1 actually just started compiling, and @module1::EXPORT does not even exist, not to mention its two routines. This makes Exporter not import anything into module2 at module2 , so when it comes to calling method_1_2() , it knows nothing about it.

The cleanest way to fix this is to do the import after compilation (including all use and BEGIN statements), but before execution. The Perl INIT block is perfect for this, and we can get the code to work by changing the modules to the form below. Here I showed only module2 , since the call pattern means that this is all that is needed to fix this particular problem, but the general case requires an equivalent change for all interacting 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; 
+3
source

The problem is that you assigned @EXPORT after it has already been used. The following is copied from the Mini-Tutorial: Mutual Use of Export Modules


[The need to use this technique is a very strong indicator of a design flaw in your system, but I understand that resources are not always available to correct design errors. ]

If ModA uses ModB, ModB uses ModA, and ModA or ModB imports characters from another, you need to pay attention to the code execution order. The best way to avoid problems is to install the 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; 
+2
source

Interestingly, I'm not sure why method_1_2 not exported to the module2 namespace, but you can get around this by explicitly referring to 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; 

Well, I think I see what is happening, but take it with salt. The use function effectively executes the BEGIN block and the BEGIN blocks are launched as soon as they are analyzed, so the code looks like this in the execution order.

  • perl starts parsing test.pl
  • he sees use module1; , so it loads module1.pm and starts its parsing
  • perl sees use module2; in module1.pm , so it loads module2.pm and starts parsing it
  • At this point, functions in module1 do not yet exist, so they cannot be imported
  • parsing continues

Something Borodin said gave me the best solution: "@ module1 :: EXPORT doesn't even exist." The problem here is that the @EXPORT variable @EXPORT not exist. This can be fixed by putting it in the 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 that prototypes in module1 will be executed in any of these cases (and I don’t how they can be since module2 compiled to module1 , so it cannot know that prototypes exist). This is another argument to never use prototypes .

+1
source

All Articles