我的项目结构:
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 {}
块中。
如果您想要更完整的答案:
首先,看一下:
-
如何用Perl有条件地导入包?
-
在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
来了解它是如何做到的。