Each sub (or more specifically, each CV), remembers which package it was originally declared in. Test case:
Foo.pm
:
package Foo;
sub import {
*{caller . "::foo"} = sub{};
}
1;
Bar.pm
:
package Bar;
use Foo;
our $bar; # introduces *Bar::bar which does not have a CODE slot
sub baz {}
1;
Accessing the symbol table now gives both foo
and baz
. By the way, I'd write that code like this (for reasons that will become clear in a moment):
my $classname = 'Bar';
for my $glob (values %{ "${classname}::" }) {
my $sub = *$glob{CODE} or next;
say *$glob{NAME};
}
Next, we have to look into the B
module to introspect the underlying C data structure. We do this with the B::svref_2object
function. This will produce a B::CV
object which has the convenient STASH
field (which returns a B::HV
object which has a NAME
field):
use B ();
my $classname = 'Bar';
for my $glob (values %{ "${classname}::" }) {
my $sub = *$glob{CODE} or next;
my $cv = B::svref_2object($sub);
$cv->STASH->NAME eq $classname or next;
say *$glob{NAME};
}
Add a few sanity checks, and this should work quite well.
Dynamic class/module loading should not be done via string eval
. Instead I recommend Module::Runtime
:
Module::Runtime::require_module($classname);