开发者

In Perl, how can I check from which module a given function was imported?

开发者 https://www.devze.com 2023-01-15 21:06 出处:网络
I have a code which calls the function. But I don\'t know the module th开发者_如何学Gois function belongs to. I need it to modify this function.

I have a code which calls the function. But I don't know the module th开发者_如何学Gois function belongs to. I need it to modify this function.

How can I check it?


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.


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.


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


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

0

精彩评论

暂无评论...
验证码 换一张
取 消