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

后端 未结 4 1180
既然无缘
既然无缘 2020-12-03 05:25

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?

相关标签:
4条回答
  • 2020-12-03 05:42

    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.

    0 讨论(0)
  • 2020-12-03 05:46

    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
    
    0 讨论(0)
  • 2020-12-03 05:52

    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 讨论(0)
  • 2020-12-03 06:01

    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.

    0 讨论(0)
提交回复
热议问题