2010-09-10 4 views
17

Ich habe einen Code, der die Funktion aufruft. Aber ich weiß nicht, zu welchem ​​Modul diese Funktion gehört. Ich brauche es, um diese Funktion zu modifizieren.In Perl, wie kann ich überprüfen, von welchem ​​Modul eine bestimmte Funktion importiert wurde?

Wie kann ich es überprüfen?

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

Sie können eine Liste mit Funktionen use:

+3

Welches Problem zu lösen, das Sie versuchen, dies durch das wissen? Es könnte einen Weg geben, das zu beheben, bevor es passiert. :) –

+0

Das Ändern von Funktionen aus anderen Klassen mag in Ruby üblich sein, ist aber eine schwarze Kunst in Perl, die für * extrem * seltene Situationen reserviert sein sollte. Warum musst du das tun? – Ether

+2

@ 'brian d foy' Drei Jahre später versuche ich einen Komponententest zu schreiben, um zu bestätigen, dass ich eine reine Perl-Version einer Funktion unter einer Bedingung bekomme, oder eine XS-Version unter einer anderen Bedingung, und plötzlich habe ich Was meiner Meinung nach ein rechtmäßiger Anwendungsfall für die Frage dieses OP ist. ;) – DavidO

Antwort

3

Wenn die Funktion von einem anderen Modul automatisch importiert wurde mit Exporter, kann sich in diesem Moduls an @EXPORT globalen Variable zu finden. Auf diese Weise werden Sie immer wissen, welches Paket eine Funktion gehört:

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

Das Devel::Peek Modul ist sehr praktisch alle Arten von Informationen über Variablen zu erhalten. Eines der Dinge, die man damit machen kann, ist ein Verweis auf ein Unterprogramm Dump und den Namen des glob es kam zu bekommen:

$ 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) 

der GVGV::GV Teil dort die wichtige Bit ist.

Eine alternative Lösung wäre Sub::Identify, die wirklich nur Namen für Code-Referenzen gibt, die Sie ihr übergeben. Wissen über Devel::Peek ist aber auch in vielen anderen Situationen praktisch, also erwähnte ich das zuerst.

+4

Das ist viel besser als das, was ich getan hätte. Ich hätte nach jedem verwendeten Modul bei '()' hinzugefügt, bis der Code nicht kompiliert werden konnte. –

8

Perls Debugger kann genau nach Ihren Wünschen graben. Zum Beispiel:

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

Es tut dies mit 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 

Sie könnten es üben mit

#! /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"; 

Ausgang:

Foo::bar

Beachten Sie, dass das obige Beispiel gibt Foo:bar ein anderer Name, aber Sie erhalten sowohl das Paket, in dem sich der Alias-Unterordner befindet, als auch seinen Namen.

1

Sie können Sub::Identify::sub_fullname jede Subroutinenreferenz passieren und es wird Ihnen das Modul zeigen, wo diese Unter definiert wurde:

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

foo(); 

Details siehe Sub::Identify

Verwandte Themen