在 Perl 中,如何检查给定函数是从哪个模块导入的?

发布于 2024-09-18 09:41:32 字数 66 浏览 9 评论 0原文

我有一个调用该函数的代码。但我不知道这个函数属于哪个模块。我需要它来修改这个功能。

我怎样才能检查它?

I have a code which calls the function. But I don't know the module this function belongs to. I need it to modify this function.

How can I check it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

本宫微胖 2024-09-25 09:41:32

Devel::Peek 模块非常方便获取有关变量的各种信息。您可以用它做的一件事是转储对子例程的引用并获取它来自的 glob 的名称:

$  perl -MDevel::Peek -MList::Util=first -e'Dump(\&first)'
SV = IV(0x1094e20) at 0x1094e28
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x11183b0
  SV = PVCV(0x10ff1f0) at 0x11183b0
    REFCNT = 3
    FLAGS = (POK,pPOK)
    PROTOTYPE = "&@"
    COMP_STASH = 0x0
    XSUB = 0x7f7ecbdc61b0
    XSUBANY = 0
    GVGV::GV = 0x11183c8        "List::Util" :: "first"
    FILE = "ListUtil.c"
    DEPTH = 0
    FLAGS = 0x800
    OUTSIDE_SEQ = 0
    PADLIST = 0x0
    OUTSIDE = 0x0 (null)

其中的 GVGV::GV 部分是重要的部分。

另一种解决方案是 Sub::Identify,它实际上只为您提供代码引用的名称。然而,了解 Devel::Peek 在许多其他情况下也很方便,所以我首先提到了这一点。

The Devel::Peek module is very handy to get all sorts of information about variables. One of the things you can do with it is dump a reference to a subroutine and get the name of the glob it came from:

$  perl -MDevel::Peek -MList::Util=first -e'Dump(\&first)'
SV = IV(0x1094e20) at 0x1094e28
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x11183b0
  SV = PVCV(0x10ff1f0) at 0x11183b0
    REFCNT = 3
    FLAGS = (POK,pPOK)
    PROTOTYPE = "&@"
    COMP_STASH = 0x0
    XSUB = 0x7f7ecbdc61b0
    XSUBANY = 0
    GVGV::GV = 0x11183c8        "List::Util" :: "first"
    FILE = "ListUtil.c"
    DEPTH = 0
    FLAGS = 0x800
    OUTSIDE_SEQ = 0
    PADLIST = 0x0
    OUTSIDE = 0x0 (null)

the GVGV::GV part in there is the important bit.

An alternative solution would be Sub::Identify, which really only gives you names for code references you hand to it. However, knowing about Devel::Peek is handy in many other situations too, so I mentioned that first.

兲鉂ぱ嘚淚 2024-09-25 09:41:32

Perl 的调试器可以按照您想要的方式进行挖掘。例如:

main::(-e:1):  0
  DB<1> sub foo {}

  DB<2> x \&foo
0  CODE(0xca6898)
   -> &main::foo in (eval 5)[/usr/share/perl/5.10/perl5db.pl:638]:2-2

它使用 Devel::Peek 来执行此操作:

=head2 C<CvGV_name_or_bust> I<coderef>

Calls L<Devel::Peek> to try to find the glob the ref lives in; returns
C<undef> if L<Devel::Peek> can't be loaded, or if C<Devel::Peek::CvGV> can't
find a glob for this ref.

Returns C<< I<package>::I<glob name> >> if the code ref is found in a glob.

=cut

sub CvGV_name_or_bust {
    my $in = shift;
    return unless ref $in;
    $in = \&$in;            # Hard reference...
    eval { require Devel::Peek; 1 } or return;
    my $gv = Devel::Peek::CvGV($in) or return;
    *$gv{PACKAGE} . '::' . *$gv{NAME};
} ## end sub CvGV_name_or_bust

来执行它

#! /usr/bin/perl

use warnings;
use strict;

package Foo;

sub bar {}

package main;

BEGIN { *baz = \&Foo::bar }

sub CvGV_name_or_bust { ... }

print CvGV_name_or_bust(\&baz), "\n";

您可以使用Output :

Foo::bar

请注意,上面的示例为 Foo:bar 提供了不同的名称,但您可以获得别名子所在的包及其名称。

Perl's debugger can dig down the way you want. For example:

main::(-e:1):  0
  DB<1> sub foo {}

  DB<2> x \&foo
0  CODE(0xca6898)
   -> &main::foo in (eval 5)[/usr/share/perl/5.10/perl5db.pl:638]:2-2

It does this using Devel::Peek:

=head2 C<CvGV_name_or_bust> I<coderef>

Calls L<Devel::Peek> to try to find the glob the ref lives in; returns
C<undef> if L<Devel::Peek> can't be loaded, or if C<Devel::Peek::CvGV> can't
find a glob for this ref.

Returns C<< I<package>::I<glob name> >> if the code ref is found in a glob.

=cut

sub CvGV_name_or_bust {
    my $in = shift;
    return unless ref $in;
    $in = \&$in;            # Hard reference...
    eval { require Devel::Peek; 1 } or return;
    my $gv = Devel::Peek::CvGV($in) or return;
    *$gv{PACKAGE} . '::' . *$gv{NAME};
} ## end sub CvGV_name_or_bust

You might exercise it with

#! /usr/bin/perl

use warnings;
use strict;

package Foo;

sub bar {}

package main;

BEGIN { *baz = \&Foo::bar }

sub CvGV_name_or_bust { ... }

print CvGV_name_or_bust(\&baz), "\n";

Output:

Foo::bar

Note that the example above gives Foo:bar a different name, but you get both the package where the aliased sub resides and also its name there.

风吹过旳痕迹 2024-09-25 09:41:32

如果该函数是使用 Exporter 从另一个模块自动导入的,则可以在此模块的 @EXPORT 全局变量中找到它:

perl -MEncode -e 'print join "\n", @Encode::EXPORT'
decode   
decode_utf8
...   

您可以提供要使用的函数列表。这样你就总能知道函数属于哪个包:

use Encode       qw[ encode ]; # encode() imported from the Encode module
use Data::Dumper qw[];         # no functions imported from Data::Dumper

If the function was automatically imported from another module using Exporter, it can be found in this module's @EXPORT global variable:

perl -MEncode -e 'print join "\n", @Encode::EXPORT'
decode   
decode_utf8
...   

You can provide a list of functions to use. This way you will always know which package a function belongs:

use Encode       qw[ encode ]; # encode() imported from the Encode module
use Data::Dumper qw[];         # no functions imported from Data::Dumper
独﹏钓一江月 2024-09-25 09:41:32

您可以将任何子例程引用传递给 Sub::Identify::sub_fullname ,它将显示定义此子例程的模块:

use Sub::Identify qw/sub_fullname/;
sub foo {
    print sub_fullname( \&foo );  # main::foo
    print sub_fullname( sub{} );  # main::__ANON__
}

foo();

有关详细信息,请参阅 Sub::Identify

You can pass to Sub::Identify::sub_fullname any subroutine reference and it will show you the module where this sub was defined:

use Sub::Identify qw/sub_fullname/;
sub foo {
    print sub_fullname( \&foo );  # main::foo
    print sub_fullname( sub{} );  # main::__ANON__
}

foo();

For details see Sub::Identify

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文