Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

How to import names from a dynamically required module

by jds17 (Pilgrim)
on Oct 02, 2012 at 21:39 UTC ( #996924=perlquestion: print w/replies, xml ) Need Help??
jds17 has asked for the wisdom of the Perl Monks concerning the following question:

I have written a module where I would like to use Role::Basic. At runtime, I want to require a specific module consuming such a role and also to import some of its names.
I could not get the import of the names right. What I tried is the following:
my $package_name = get_package_name(); eval "require $package_name"; eval "$package_name->import( qw( method1 method2 method3 )";
Here, $package_name is the fully qualified name of the role consuming package determined at runtime and method1,... are methods exported by this package.
What I get as an error is:
Undefined subroutine &MyPackage::num_records called at ...
where MyPackage is the name of the current package (i.e. the one the above code is in) and not the desired one, i.e. $package_name.

Replies are listed 'Best First'.
Re: How to import names from a dynamically required module
by tobyink (Abbot) on Oct 02, 2012 at 22:06 UTC
    if (eval "require $package_name; 1") { $package_name->import(qw/method1 method2 method3/); }

    It's often a good idea to lift imports to compile-time using a BEGIN block.

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      Thank you very much, tobyink, I was not aware of the fact that one could call import on package names as in your example. This solved my issue.

        This is not specific to import; it works with all class method calls...

        use Math::BigInt; my $class = "Math::BigInt"; my $six = $class->new(6); my $seven = "Math::BigInt"->new(7); my $eight = join("::", "Math", "BigInt")->new(8);

        In fact, string quoting class names is arguably a much better idea than the more conventional Math::BigInt->new(9), because the latter will start behaving surprisingly if there's ever a BigInt sub defined in the Math package.

        perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: How to import names from a dynamically required module
by chromatic (Archbishop) on Oct 02, 2012 at 23:02 UTC

    Use something Class::Load rather than eval STRING; almost no one checks $package_name for sanity. If that comes from anything at all untrusted, you have a code injection vulnerability.

    Improve your skills with Modern Perl: the free book.

      chromatic, you are right. I will strip out eval completely and use Class::Load.
Re: How to import names from a dynamically required module
by kejohm (Hermit) on Oct 02, 2012 at 22:21 UTC

    There is a syntax error in your second eval; you are missing a ), so the code isn't being executed. After evaling code you should either check the value of the $@ variable, or check the return value from eval, like tobyink's example above.

      Thanks, kejohm. You are right, that was a stupid error on my side. I like the version without the eval as in tobyink's example better in any case.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://996924]
Approved by tobyink
[Corion]: Hurr - those people from that shady VPN / proxy backdoor site are persistent - today is the third time they've mailed me about backdooring my software with their "SDK".
[Corion]: I guess I should blacklist them on my mailserver directly.

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (9)
As of 2018-05-21 14:03 GMT
Find Nodes?
    Voting Booth?