Perl自定义模块函数导入问题:调用person_init时报未定义子例程错误
首先,咱们来看你遇到的错误:Undefined subroutine &main::person_init called(你提供的错误信息里写的是Person_Init,应该是笔误,实际是小写的person_init),根源主要是模块包名和目录结构不匹配导致的。
问题分析
你的目录结构是:
TestObject.pl Person/ Person.pm PersonInit.pm
Perl对模块的包名有严格要求:包名必须和文件所在的目录结构对应。比如:
Person/Person.pm的包名是Person(这部分你已经写对了)Person/PersonInit.pm的包名应该是Person::PersonInit,但你现在写的是package PersonInit;——这就导致Perl无法正确关联模块路径和包名,use Person::PersonInit;加载的模块实际属于PersonInit包,导出的函数也在这个包下,主脚本的main包自然找不到这个函数。
修复步骤
1. 修正PersonInit.pm的包名
打开Person/PersonInit.pm,把第一行的包名改成:
package Person::PersonInit;
2. (可选)简化模块内的库路径设置
你的主脚本TestObject.pl已经通过use lib $RealBin;设置了正确的库路径,所以PersonInit.pm里的use FindBin和use lib可以去掉(留着也不影响,但没必要重复设置)。修改后的开头部分如下:
#!/usr/bin/perl package Person::PersonInit; use strict; use POSIX; use warnings; use Person::Person; use Exporter; our @ISA= qw( Exporter ); our @EXPORT_OK = qw( person_init ); our @EXPORT = qw( person_init );
3. 确认函数调用的大小写一致性
Perl是大小写敏感的,确保你在TestObject.pl里调用的是person_init()(全小写),和模块里定义的函数名完全一致(你的代码里已经是对的,只要别写成Person_Init就好)。
测试修复
现在重新运行TestObject.pl,应该就能正确调用person_init函数了。这个函数会创建一个Person对象,打印默认的nom值(inconnu)和toto,然后主脚本再打印toto,最终输出应该是:
inconnutotototo
额外小建议
模块里的对象属性(比如_NOM、_PRENOM)最好通过访问器方法(getter/setter)来访问,而不是直接读取哈希键,这样更符合面向对象的封装原则。比如在Person.pm里添加:
sub get_nom { my ($self) = @_; return $self->{_NOM}; }
之后在PersonInit.pm里就可以用$Person->get_nom()代替$Person->{_NOM}啦。
内容的提问来源于stack exchange,提问作者bussirs

