如何从Perl子程序引用中获取对应的子程序名称?
Perl中如何从子程序引用获取名称或源代码?
我在Perl代码中定义了很多类似$wprAtnA、$wprAtnB的哈希对象,其中code字段存储子程序引用,arg字段存储参数集合。其他代码接收这些对象后会调用对应的子程序。但用Data::Dumper或直接打印子程序引用时,只能看到类似CODE(0x...)或sub { "DUMMY" }的信息,无法直接识别对应的子程序。想知道有没有办法通过子程序引用恢复其名称,或者获取源代码,方便调试和识别。
原测试代码
#!/usr/bin/env perl use strict; use warnings; use feature 'say'; use Data::Dumper qw(Dumper); $Data::Dumper::Sortkeys = 1; sub dog { say 'we are in ',[caller(0)]->[3],; return 1; } sub feline { die; } my$wprAtnA= { code=>\&dog, arg => { x=>5, } }; my$wprAtnB= { code=>\&feline, arg => { verbose=>0, text=>'why?', } }; say $wprAtnA->{code}; print Dumper $wprAtnA; say $wprAtnB->{code}; print Dumper $wprAtnB;
运行结果
> perl d.pl CODE(0x7f96dc80e948) $VAR1 = { 'arg' => { 'x' => 5 }, 'code' => sub { "DUMMY" } }; CODE(0x7f96db853a80) $VAR1 = { 'arg' => { 'text' => 'why?', 'verbose' => 0 }, 'code' => sub { "DUMMY" } };
解决方案
获取子程序名称
使用Perl核心模块Sub::Util中的subname函数,可以直接获取子程序引用对应的完整名称(包含包名,默认包为main::)。示例代码如下:
#!/usr/bin/env perl use strict; use warnings; use feature 'say'; sub dog() { say 'we are in ',[caller(0)]->[3],; return 1; } use Sub::Util qw( subname ); say subname(\&dog); my$wprAtnA= { code=>\&dog, arg => { x=>5, } }; say subname($wprAtnA->{code});
运行这段代码会输出:
main::dog main::dog
获取子程序源代码(反编译)
如果需要查看子程序的具体代码逻辑,可以使用B::Deparse模块反编译子程序引用。示例:
use strict; use warnings; use feature 'say'; use B::Deparse; sub dog { say 'we are in ',[caller(0)]->[3]; return 1; } my $deparser = B::Deparse->new(); say $deparser->coderef2text(\&dog);
运行结果会输出反编译后的代码:
{ say 'we are in ', [caller(0)]->[3]; return 1; }
注意:反编译的结果可能和原代码格式略有差异,但逻辑一致。如果子程序是动态生成的匿名子程序,则无法获取原始名称,但依然可以反编译查看逻辑。
内容的提问来源于stack exchange,提问作者Jacob Wegelin
相关产品推荐
相关产品推荐

