如何从自定义模块中正确导入函数
Posted
技术标签:
【中文标题】如何从自定义模块中正确导入函数【英文标题】:How to correctly import a function from a custom module 【发布时间】:2020-01-20 12:20:03 【问题描述】:我需要一些关于如何从 perl 中的自定义模块正确导入函数的线索。 (这里是 PersonInit 模块中的 person_init)。
这是我的文件夹表示:
TestObject.pl
Person/Person.pm
Person/PersonInit.pm
这是TestObject.pl的代码
use FindBin 1.44 qw( $RealBin );
use lib $RealBin;
use warnings; # Avertissement des messages d'erreurs
use strict;
use Person::PersonInit;
person_init();
print('toto');
在 Person.pm 中:
package Person; # Nom du package, de notre classe
use warnings; # Avertissement des messages d'erreurs
use strict; # Vérification des déclarations
use Carp; # Utile pour émettre certains avertissements
sub new
my ( $classe, $ref_arguments ) = @_;
# Vérifions la classe
$classe = ref($classe) || $classe;
# Création de la référence anonyme de hachage vide (futur objet)
my $this = ;
# Liaison de l'objet à la classe
bless $this, $classe;
if (! ( defined $ref_arguments->nom ))
$ref_arguments->nom = 'inconnu';
$this->_NOM = $ref_arguments->nom;
$this->_PRENOM = $ref_arguments->prenom;
$this->_TEL = $ref_arguments->tel;
$this->_MAIL = $ref_arguments->mail;
$this->_GRADE = $ref_arguments->grade;
$this->_SEXE = $ref_arguments->sexe;
$this->_SERVICE = $ref_arguments->service;
return $this;
1; # Important, à ne pas oublier
__END__
在 PersonInit.pm 中:
#/usr/bin/perl
package PersonInit;
use strict;
use POSIX;
use warnings;
use FindBin 1.44 qw( $RealBin );
use lib $RealBin;
use Person::Person;
use Exporter;
our @ISA= qw( Exporter );
# these CAN be exported.
our @EXPORT_OK = qw( person_init );
# these are exported by default.
our @EXPORT = qw( person_init );
sub person_init
my ($arg) = @_;
my $Person = Person->new(
prenom => 'Jean',
sexe => 'M',
tel => '3',
mail => '4',
grade => 'g',
service => 's',
);
print ($Person->_NOM);
print ('toto');
return $Person;
;
1;
所以当我尝试启动时,我遇到了这个错误:
在 D:\Workspace\Mapping\TestObject.pl 第 8 行调用的未定义子例程 &main::Person_Init。
【问题讨论】:
【参考方案1】:为获得最佳效果,您使用的包名称应与您提供给use
指令的包名称相匹配。使用
package Person;
...
package PersonInit;
...
use Person;
use PersonInit;
或
package Person::Person;
...
package Person::PersonInit;
...
use Person::Person;
use Person::PersonInit;
但不是
package Person;
...
package PersonInit;
...
use Person::Person;
use Person::PersonInit;
【讨论】:
补充一点:use 语句记录了两件事。第一个是require
模块,需要传递与其文件路径对应的名称,::
翻译成/
。第二种是从模块到import
,需要传递包名。因此,要让这两者在一个 use
语句中工作,文件路径和包名称必须匹配。【参考方案2】:
我怀疑您没有共享您实际使用的代码,因为我没有收到您描述的错误,但我收到了大量其他错误。
我得到的错误都归结为模块路径和包名称之间的链接混淆。因为您的模块文件位于名为“Person”的目录中,所以它们实际上应该被称为“Person::Person”和“Person::PersonInit”。您似乎意识到,在加载模块时 (use Person::Person
),但在命名包 (package Person
) 或调用类方法 (Person->new(...)
) 时却没有。
一旦我编辑了您的文件以始终使用正确的包名称,一切都按预期工作。
我会注意到您同时定义了@EXPORT
和@EXPORT_OK
。您导出的子例程只需要在其中之一中即可。
我正在使用 Perl 5.26.1。从您问题上的标签来看,您似乎正在使用 5.8.something (我猜它可能是 5.8.8)。您可能会遇到自该版本发布以来已在 13 多年内修复的错误 - 但是,老实说,我不记得听说过类似的事情。无论如何,我强烈建议您升级到更新版本的 Perl。
【讨论】:
我可以通过运行他提供的代码来重现 OP 的问题。我唯一需要做的就是在 PersonInit.pm 中将package PersonInit
替换为 package Person::PersonInit
。 (同样的事情应该在 Person.pm 中完成,但是当我运行它时不会导致任何错误)(使用 perl 5.22 btw)以上是关于如何从自定义模块中正确导入函数的主要内容,如果未能解决你的问题,请参考以下文章
如何在模块化的 java 11 应用程序中动态加载 Libreoffice jar,而不从自定义类加载器中获取 ClassCastException