cfreak has asked for the wisdom of the Perl Monks concerning the following question:

I think I understand why this doesn't work but I'm having trouble coming up with a way around it.

I'm working on a bot that can talk on a variety of protocols. I want to be able to load the appropriate protocol when the bot starts and keep the code for each protocol in its own separate package. To do this I used the following code:

sub init { my $pkg = shift; my $proto = shift || $config->protocol(); no strict 'refs'; eval "require Bot::Protocol::$proto"; if($@) { croak "Failed to load $proto.\n"; } }

So far, so good. This works as long as my Bot::Protocol::$proto simply executes. However, I'd like to pass parameters to my protocols so that I don't have to include the config again etc. I tried using Exporter within the file I was requiring and then calling the sub. I tried a test case to eliminate the irrelavent parts

# in the main my $pkg = shift; no strict 'refs'; eval "require $pkg"; if($@) { croak "Failed to load $pkg: $@\n"; } print foobar();

And with the test I wrote two small packages, 'Foo' and 'Bar':

# in Foo.pm package Foo; use strict; use Exporter; use vars qw(@ISA @EXPORT); @ISA = qw(Exporter); @EXPORT = qw(foobar); sub foobar { return "Foo!"; } 1;

(Bar.pm looks the same except it returns "Bar")

However of course I get "Undefined subroutine &main::foobar(). Now if I call it directly after I've required it with the eval, i.e. Foo::foobar() it works but to do that in my project I would have to use eval again as in eval "$pkg::foobar()", which seems a bit redundant. There must be a way to export it to everyone. Thanks in advance!

Lobster Aliens Are attacking the world!

Replies are listed 'Best First'.
Re: Exporting subs from package required in an eval
by chromatic (Archbishop) on Jun 25, 2003 at 01:23 UTC

    use calls require and then import(). If you need to import symbols, you'll have to call import() manually. Untested, almost pseudo-code follows:

    my $package = "Bot::Protocol::$proto"; eval { require $package }; $package->import();

      Sorry for grave-digging, but this seems to be the closest thread that search manages to discover.

      I'm trying to use a runtime-determined module (a game rules plugin for a game server). I want to import some functions and scalars into main namespace. Both eval "use $modulename"; and "eval require then manually import" as described above import the subs successfully, but fail to import scalars. I could, of course, manage with wrapping scalars into getter-setter functions but something seems funny here... Could anyone explain/help?

      main.pl

      use strict; use warnings; my $x='Exports'; eval "use $x"; asub(); #fails if I uncomment the next line - Global symbol "$ascalar" require +s explicit package name #print $ascalar, "\n";

      Exports.pm

      package Exports; use strict; use warnings; use Exporter; use base 'Exporter'; our @EXPORT = qw( $ascalar asub); our $ascalar = 42; sub asub { print "sub called\n"; } 1;
      I'm using latest ActivePerl on Windows This is perl, v5.10.1 built for MSWin32-x86-multi-thread (with 2 registered patches, see perl -V for more detail) Copyright 1987-2009, Larry Wall Binary build 1007 291969 provided by ActiveState http://www.ActiveState.com Built Jan 26 2010 23:15:11

        You can't do that. As use strict; does not know that you'll be declaring these variables later on at runtime, it raises an error. Either declare those variables in your main program, or load your plugin at compile time in a BEGIN block. See use.