如何在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中动态加载插件呢?

有什么好的框架可以帮助我吗?

谢谢。

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

这基本上就是你所需要的;不复杂到需要模块。如果您需要在模块编译的早期将其封装在BEGIN {}块中。

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

首先,看一下:

  1. 如何用Perl有条件地导入包?

  2. 在Perl中,使用模块比需要文件更好吗?

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

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() 调用它

此外,这整件事最好放在Test.pm模块的BEGIN {};中。否则import()可能不会生效。

require加载一个模块:

require "Plugins/Plugin1.pm";

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

use用于编译时。

模块:PluginFinder

use Module::PluginFinder qw( );
my $finder = Module::PluginFinder->new(
   search_path => 'Plugins',
);
my $test = $finder->construct("Plugin1");
$test->run();

如果您想对错误进行特殊处理:

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
    ...;
  }
  ...;
}

充分的方法是:

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

您可以查看现代框架Mojolicus Mojo::Loader来了解它是如何做到的。

最新更新