2012-01-09 88 views
0

我的項目結構:如何在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中動態加載插件呢?

有沒有什麼好的框架可以幫助我?

謝謝。

+0

http://stackoverflow.com/questions/2025261/how-can-i-find-all-the-packages-that-inherit-from-a-package-in-perl http://stackoverflow.com/問題/ 2478009/how-do-i-write-perl-object-with-plugins http://stackoverflow.com/questions/4815432/what-is-the-best-option-for-building-a-plugin-system -for-a-moose-application http://stackoverflow.com/questions/8301959/dynamically-loading-perl-modules – daxim 2012-01-09 14:56:08

回答

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 ([email protected]) { 
    warn "Error including Foobar: [email protected]"; 
} 

但對於你的情況,因爲你的模塊名稱可能是一個字符串,你需要:

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

import將允許您使用Plugin1已經導出的子程序。例如如果func()Plugin1出口,你可以用func()調用它,而不是Plugin1::func()

而且這件事是最好把在BEGIN {};Test.pm模塊中。否則import()可能無法生效。

+0

另外,看看'Module :: Load'。它可以爲你節省時間和精力。 – 2017-07-12 10:06:20

+0

當'Path/Plugin1.pm'時會失敗 – 2018-01-12 19:26:36

2

require加載模塊:

require "Plugins/Plugin1.pm"; 

就會失敗,所以你需要處理錯誤。

use用於編譯時。

4
eval { 
    require $plugin; 
} 
if([email protected]) # try another one or report error or whatever ... 

這基本上都是你需要的;不夠複雜,需要一個模塊。如果您需要在編譯模塊期間儘早完成,可以將其包裝在BEGIN {}塊中。

+0

這是不對的。如果'$ plugin'沒有文件名,這將失敗。這裏是更好的方法:'eval「需要$ plugin; 1」' – 2018-01-12 19:18:34

2

Module::PluginFinder

use Module::PluginFinder qw(); 

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

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

如果你想要做的錯誤的東西特別:

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

否則就用:

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

的充分做法是:

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

你可以看看現代的框架MojoliciousMojo::Loader看看是如何完成的。