【问题标题】:How to dynamic load plugin files in perl?如何在 perl 中动态加载插件文件?
【发布时间】:2012-01-09 06:28:14
【问题描述】:

我的项目结构:

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

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

谢谢。

【问题讨论】:

标签: perl


【解决方案1】:
eval {
    require $plugin;
}
if($@) # try another one or report error or whatever ...

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

【讨论】:

  • 这不是正确的做法。如果 $plugin 不是文件名,这将失败。这是更好的方法:eval "require $plugin; 1"
【解决方案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?

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

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() 可能不会生效。

【讨论】:

  • 另外,看看Module::Load。这将为您和其他人节省时间和精力。
  • Path/Plugin1.pm 时会失败
【解决方案3】:

require 加载一个模块:

require "Plugins/Plugin1.pm";

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

use 用于编译时。

【讨论】:

    【解决方案4】:

    Module::PluginFinder

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

        充分的方法是:

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

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

        【讨论】:

          猜你喜欢
          • 2018-02-11
          • 1970-01-01
          • 1970-01-01
          • 2021-05-19
          • 1970-01-01
          • 2019-03-16
          • 2013-08-15
          • 1970-01-01
          • 2014-07-19
          相关资源
          最近更新 更多