我浪费了很多天在一个更大的代码块上,其中包含Exporter
语句,这些代码块在大约一年前曾经工作过。对此的几种变体都失败了,包括安装./FOO/BAR/Foobar.pm
,这标志着成功。
我正在使用Windows 10,Perl v5.26.0,为MSWin32-x64多线程构建
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 "donen";
./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 "Loadedn";
$FOO = q{some val};
}
1;
执行转储
perl Caller.pl
try FOO::BAR::Foobar::foo()
Undefined subroutine &FOO::BAR::Foobar::foo called at Caller.pl line 12.
这是怎么回事?我应该放弃使用Exporter
吗?但是,如何跨模块链接功能呢?
有三件事出错:
-
有了
FOO::BAR::Foobar::foo()
:没有这样的sub
,只有Foobar::foo()
。 -
使用
foo()
:use FOO::BAR::Foobar;
等价于BEGIN { require FOO::BAR::Foobar; FOO::BAR::Foobar->import() }
,但是在包FOO::BAR::Foobar
中没有可用的方法import
,因为您要将Exporter
继承到包Foobar
中。 -
使用
foo()
: 你使用的是@EXPORT_OK
而不是@EXPORT
,这意味着你需要显式导入foo
,但你没有在use FOO::BAR::Foobar;
这样做。
因此,需要两件事来解决此问题:
-
正如@HåkonH ægland在评论中已经指出的那样,将
package Foobar;
更改为package FOO::BAR::Foobar;
。 -
将
use FOO::BAR::Foobar;
更改为use FOO::BAR::Foobar qw/foo/;
。
然后你展示的代码就可以工作了 - 没有必要放弃Exporter
.我只是推荐一种不同的使用Exporter
风格:而不是通过@ISA
继承,只需将import
导入到您的包中即可。以下是我./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 "Loadedn";
$FOO = q{some val};
}
1;