Как динамически загружать файлы плагинов в Perl? - PullRequest
0 голосов
/ 09 января 2012

Структура моего проекта:

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

test.pm выглядит следующим образом:

sub new{
#how to dynamic load plugins?

plugin1, pluggs2 предоставляют те же API, скажем, sub run {#...}

perlСценарий выглядит так:

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

Итак, как динамически загружать плагины в test.pm?

Есть ли какая-нибудь хорошая структура, которая может мне помочь?

Спасибо.

Ответы [ 6 ]

4 голосов
/ 09 января 2012
eval {
    require $plugin;
}
if($@) # try another one or report error or whatever ...

Это в основном все, что вам нужно;не достаточно сложный, чтобы нуждаться в модуле.Вы можете обернуть его в блок BEGIN {}, если вам нужно сделать это рано во время компиляции модуля.

2 голосов
/ 09 января 2012

Если вы хотите более полный ответ:

Сначала взгляните на:

  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()

Также все это лучше поместить в BEGIN {}; в вашем Test.pm модуле. В противном случае import() может не вступить в силу.

2 голосов
/ 09 января 2012

Модуль :: PluginFinder

use Module::PluginFinder qw( );

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

my $test = $finder->construct("Plugin1");
$test->run();
2 голосов
/ 09 января 2012

require загружает модуль:

require "Plugins/Plugin1.pm";

Это может привести к сбою, поэтому вам нужно обрабатывать ошибки.

use для времени компиляции.

1 голос
/ 09 января 2012

Если вы хотите сделать что-то особенное с ошибками:

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
    ...;
  }
  ...;
}
0 голосов
/ 12 января 2018

Достаточный подход:

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

Вы можете заглянуть в современные рамки Mojolicious Mojo::Loader, чтобы увидеть, как это сделано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...