如何在perl中动态加载插件文件?

时间:2012-01-09 06:28:14

标签: perl

我的项目结构:

Test.pm
Plugins/Plugin1.pm
Plugins/Plugin2.pm

test.pm看起来像:

sub new{
#how to dynamic load plugins?

plugin1,plugs2提供相同的api,比如sub run {#...}

perl脚本看起来像:

my $test=Test->new("Plugin1");
$test->run ;#should call Plugin1->run

那么如何在test.pm中动态加载插件?

有没有好的框架来帮助我?

感谢。

6 个答案:

答案 0 :(得分:4)

eval {
    require $plugin;
}
if($@) # try another one or report error or whatever ...

这基本上就是你所需要的;不够复杂,不需要模块。如果需要在编译模块期间尽早完成,可以将其包装在BEGIN {}块中。

答案 1 :(得分:2)

require加载一个模块:

require "Plugins/Plugin1.pm";

这可能会失败,因此您需要处理错误。

use用于编译时。

答案 2 :(得分:2)

Module::PluginFinder

use Module::PluginFinder qw( );

my $finder = Module::PluginFinder->new(
   search_path => 'Plugins',
);

my $test = $finder->construct("Plugin1");
$test->run();

答案 3 :(得分:2)

如果您想要更完整的答案:

首先,看看:

  1. How can I conditionally import a package in Perl?

  2. In Perl, is it better to use a module than to require a file?

  3. 第一个链接中问题的答案是你想要的:

    eval {
        require Plugin1;
        Plugin1->import();
    };  
    if ($@) {
        warn "Error including Foobar: $@";
    }
    

    但是对于你的情况,因为你的模块名称可能是一个字符串,你需要:

    eval {
        my $module_name = 'Plugin1.pm';
        require $module_name;
        $module_name =~ s/\.pm//;
        $module_name->import();
    };
    if ($@) {
        # handle error here
    }
    

    import将允许您使用Plugin1中已导出的子例程。例如如果func()导出Plugin1,您可以使用func()而不是Plugin1::func()

    来调用BEGIN {};

    此外,Test.pm模块中import()更好地放入了这一切。否则{{1}}可能不会生效。

答案 4 :(得分:1)

如果你想对错误做一些特别的事情:

sub new {
  my $class = shift;
  ...;
  for my $plugin (@_){
    if( eval "require $plugin" ){
      # successful
      ...;
    }else{
      # unsuccessful
      die $@;
    }
  }
  ...;
}

否则只需使用:

sub new {
  my $class = shift;
  ...;
  for my $plugin (@_){
    eval "require $plugin" or die $@;
    # successful
    ...;
  }
  ...;
}

答案 5 :(得分:0)

足够的方法是:

eval "require $plugin_class; 1"   or die "Error";

您可以查看现代框架Mojolicious Mojo::Loader,看看它是如何完成的。