【问题标题】:Modules use each other in cycle. Compilation error in Perl模块循环使用。 Perl 中的编译错误
【发布时间】:2016-10-25 09:06:50
【问题描述】:

有3个模块,所以它们按模式相互使用 a -> b -> c -> a。我无法编译这种情况。

例如,

我得到一个编译错误

"Throw" is not exported by the LIB::Common::Utils module
Can't continue after import errors at /root/bin/ppm/LIB/Common/EnvConfigMgr.pm line 13
BEGIN failed--compilation aborted at /root/bin/ppm/LIB/Common/EnvConfigMgr.pm line 13.

Utils.pm

use Exporter qw(import);
our @EXPORT_OK = qw(
        GetDirCheckSum
        AreDirsEqual
        onError
        Throw);
use LIB::Common::Logger::Log;

日志.pm

use Log::Log4perl;

use LIB::Common::EnvConfigMgr qw/Expand/;

EnvConfigMgr.pm

use Exporter qw(import);

our @EXPORT = qw(TransformShellVars ExpandString InitSearchLocations);
our @EXPORT_OK = qw(Expand);

use LIB::Common::Utils qw/Throw/;

为什么不编译以及如何使其工作?

【问题讨论】:

  • 您还应该为您要导出的函数包含存根,以便我们可以复制/粘贴并尝试。
  • 正如 simbabque 所说,我们需要看到的远不止这些。请显示使用这些模块并显示相同问题的main.pl

标签: perl exporter


【解决方案1】:

你需要在依赖循环的某处使用require而不是use,以延迟绑定。使用不导出任何内容的模块最为方便,否则您需要编写显式的import 调用

在你的情况下LIB::Common::Logger::Log 不使用Export,所以放

require LIB::Common::Logger::Log

进入LIB/Common/Utils.pm 修复问题

您可以访问不工作的代码,并且只需显示故障代码即可为我们节省大量时间。你忽略了两个要求更多信息的 cmets,所以我已经设置了这些文件

请注意,这段代码什么都不做:它只是编译

LIB/Common/Utils.pm

package LIB::Common::Utils;

use Exporter 'import';

our @EXPORT_OK = qw/
    GetDirCheckSum
    AreDirsEqual
    onError
    Throw
/;

require LIB::Common::Logger::Log;

sub GetDirCheckSum { }

sub AreDirsEqual { }

sub onError { }

sub Throw { }

1;

LIB/Common/Logger/EnvConfigMgr.pm

package LIB::Common::EnvConfigMgr;

use Exporter 'import';

our @EXPORT = qw/ TransformShellVars ExpandString InitSearchLocations /;
our @EXPORT_OK = 'Expand';

use LIB::Common::Utils 'Throw';

sub TransformShellVars { }

sub ExpandString { }

sub InitSearchLocations { }

sub Expand { }

1;

LIB/Common/Logger/Log.pm

package LIB::Common::Logger::Log;

use Log::Log4perl;

use LIB::Common::EnvConfigMgr 'Expand';

1;

main.pl

use strict;
use warnings 'all';

use FindBin;
use lib $FindBin::Bin;

use LIB::Common::Utils;

【讨论】:

  • 你能输入短语“...延迟绑定...”的详细信息吗?
  • @osiv:后期绑定这个词在这里有点用词不当。它恰当地引用了面向对象的概念,根据继承的原则,方法调用在运行时解决,而不是在编译时解决。这是 Perl 使用的方法。我的意思是在运行时确定任何标识符的含义的更一般的想法。
  • @osiv: use 使用隐式 BEGIN 块,因此在编译阶段编译模块并导入任何符号。 require 在运行时执行,因此您可以通过使用至少一个 require 来打破依赖循环,当循环变成一个有开始和结束的 时。由于这个原因,您经常会在 CPAN 模块中看到 require
猜你喜欢
  • 1970-01-01
  • 2022-11-05
  • 2015-09-28
  • 1970-01-01
  • 2015-06-24
  • 2016-05-29
  • 1970-01-01
  • 2011-12-19
  • 2020-02-23
相关资源
最近更新 更多