Richard Simões
Richard Simões

Reputation: 12791

Can I dynamically get a list of functions or function names from any Perl module?

I would like to dynamically get a list of either function names (as strings) or function references from any arbitrary Perl module available on my system. This would include modules that may or may not have, e.g., a global @EXPORT_OK array in its namespace. Is such a feat possible? How does one pull it off if so?

Edit: From reading perlmod, I see that %Some::Module:: serves as a symbol table for Some::Module. Is this the correct place to be looking? If so, how can I whittle the table down to just the function names in Some::Module?

Upvotes: 9

Views: 5751

Answers (3)

solstice333
solstice333

Reputation: 3649

I'm using Perl 5.20. This works on my machine:

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

Upvotes: 1

Ether
Ether

Reputation: 53966

You may find this simple script handy:

#!/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: $@" if $@;

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

But, if you're doing this in production code, I'd use Package::Stash instead:

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

Upvotes: 8

DVK
DVK

Reputation: 129363

You're on the right track. To wittle down the full symbol table to just the subs, something like this can be done (Hat tip "Mastering Perl", ch 8, for main package version of this):

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

Upvotes: 9

Related Questions