Why doesn't my package export names in `@EXPORT`?

45 Views Asked by At

I'm tying to provide some special constants via the autoload function. Basically creating the functions works fine, but the code would allow to create any name for the constants instead of a specific allowed set.

So I tried limiting the names by exporting them from the generating package.

Unfortunately the package exports noting at all, and I don't see the error.

The demonstration code is this:

#!/usr/bin/perl
use warnings;
use strict;

# Tell Perl module is loaded already (fake)
sub UNIVERSAL::_fake_load($)
{
    my $pkg = $_[0];

    # Tell Perl module is loaded already
    $INC{join('/', split(/::/, $pkg)) . '.pm'} = 1;
}

package MAGIC_STUFF;

our (@EXPORT, @ISA, $VERSION);

BEGIN {
    use Exporter;
    $Exporter::Verbose = 1;
    $VERSION = 'v0.0.0';                # for version checking
    @ISA = qw(Exporter);
    @EXPORT = qw(abra ka dabra);        # exported by default
}

use AutoLoader;

sub AUTOLOAD {
    use vars qw($AUTOLOAD);
    my ($sub_name, @args) = ($AUTOLOAD, @_);
    no strict 'refs';

    *$sub_name = sub { "$sub_name defined for (" . join(',', @args). ")" };
    goto &$sub_name;                    # return from AUTOLOAD
}

sub import
{
    print "import: ", join(' ', @_), "\n";
    Exporter::import(@_);
}

BEGIN {
    $DB::single = 1;
    foreach (@EXPORT) {
        eval "sub $_;";
    }
    __PACKAGE__->_fake_load();
}

1;

package main;


use MAGIC_STUFF;
#MAGIC_STUFF->import(1,2,3);

print MAGIC_STUFF::joe(7), "\n";
print ka(3), "\n";

When debugging it, I see this essentially:

> perl -d test.pl

Loading DB routines from perl5db.pl version 1.39_10
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

MAGIC_STUFF::CODE(0x16d17b0)(test.pl:45):
45:         foreach (@EXPORT) {
#...
  DB<1> n
MAGIC_STUFF::CODE(0x16d17b0)(test.pl:46):
46:             eval "sub $_;";
  DB<1> n
MAGIC_STUFF::CODE(0x16d17b0)(test.pl:46):
46:             eval "sub $_;";
  DB<1> n
MAGIC_STUFF::CODE(0x16d17b0)(test.pl:46):
46:             eval "sub $_;";
  DB<1> n
MAGIC_STUFF::CODE(0x16d17b0)(test.pl:48):
48:         __PACKAGE__->_fake_load();
  DB<1> n
import: MAGIC_STUFF
Importing into MAGIC_STUFF from MAGIC_STUFF: abra, dabra, ka at test.pl line 40.
        MAGIC_STUFF::import('MAGIC_STUFF') called at test.pl line 56
        main::BEGIN() called at test.pl line 56
        eval {...} called at test.pl line 56
MAGIC_STUFF::(test.pl:16):      our (@EXPORT, @ISA, $VERSION);
  DB<1> n
MAGIC_STUFF::(test.pl:51):      1;
  DB<1> n
main::(test.pl:59):     print MAGIC_STUFF::joe(7), "\n";
  DB<1> n
MAGIC_STUFF::joe defined for (7)
main::(test.pl:60):     print ka(3), "\n";
  DB<1>
Undefined subroutine &main::ka called at test.pl line 60.
 at test.pl line 60.
Debugged program terminated.  Use q to quit or R to restart,

The foreachloop was an attempt to fix the problem, but it did not help.

What confuses me most is

Importing into MAGIC_STUFF from MAGIC_STUFF

Shouldn't it import into main?

1

There are 1 best solutions below

0
ikegami On BEST ANSWER

Exporter::import exports to its caller's namespace. The caller is MAGIC_STUFF::import, so you're exporting to the MAGIC_STUFF namespace.

A simple fix is to use goto to remove MAGIC_STUFF::import from the call stack. The caller of MAGIC_STUFF::import thus becomes the caller of Exporter::import. (@_ is provided unchanged to new sub.)

sub import
{
    print "import: ", join(' ', @_), "\n";
    goto &Exporter::import;
}