2010-12-09 2 views
6

Я хотел бы динамически получить список имен функций (как строк) или ссылок на функции из любого произвольного модуля Perl, доступного в моей системе. Это включает модули, которые могут иметь или не иметь, например, глобальный массив @EXPORT_OK в своем пространстве имен. Возможно ли такое достижение? Как это можно сделать, если так?Могу ли я динамически получить список функций или имен функций из любого модуля Perl?

Edit: От чтения perlmod, я вижу, что %Some::Module:: служит в качестве таблицы символов для Some::Module. Это правильное место для поиска? Если да, то как я могу свести таблицу вниз к именам функций в Some::Module?

ответ

7

Вы на правильном пути. Чтобы wittle вниз полная таблицы символов для всего подлодок, что-то, как это может быть сделано (Hat наконечник «Mastering Perl», глава 8, для основного пакета версии этого):

use strict; # need to turn off refs when needed 
package X; 

sub x {1;}; 
sub y {1;}; 
our $y = 1; 
our $z = 2; 

package main; 

foreach my $entry (keys %X::) { 
    no strict 'refs'; 
    if (defined &{"X::$entry"}) { 
     print "sub $entry is defined\n" ; 
    } 
} 

# OUTPUT 
sub y is defined 
sub x is defined 
+0

Уход. Я думаю, что я был близок к этому, изучая представление CPAN, «Символ :: Таблица», но его способы немного продвинуты для меня. – 2010-12-10 01:07:25

7

Вы можете найти этот простой скрипт под рукой:

#!/usr/bin/env perl 
use strict; 
use warnings;  
use Data::Dumper; 

# dump of object's symbol table: 
foreach my $className (@ARGV) 
{ 
    print "symbols in $className:"; 

    eval "require $className"; 
    die "Can't load $className: [email protected]" if [email protected]; 

    no strict 'refs'; 
    print Dumper(\%{"main::${className}::"}); 
} 

Но, если вы делаете это в рабочем коде, я использовал бы вместо Package::Stash:

my @subs_in_foo = Package::Stash->new('Foo')->list_all_symbols('CODE'); 
+0

Рад, что вы сказали `use strict` и верхний и` no strict 'refs'`, где необходимо. – Narveson 2010-12-10 03:57:07

0

Я использую Perl 5.20 , Это работает на моей машине:

use strict; 

package foo; 
    our $some_var; 
    sub func1 { return 'func1'} 
    sub func2 { return 'func2'} 

package main; 
    sub callable { 
     my ($x) = @_; 
     return defined(&$x); 
    } 

    while (my ($k, $v) = each(%foo::)) { 
     if (callable($v)) { 
     print("$k\n"); 
     } 
    } 

    # output: 
    # func1 
    # func2