我的项目结构:
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 :(得分:4)
eval {
require $plugin;
}
if($@) # try another one or report error or whatever ...
这基本上就是你所需要的;不够复杂,不需要模块。如果需要在编译模块期间尽早完成,可以将其包装在BEGIN {}
块中。
答案 1 :(得分:2)
答案 2 :(得分:2)
use Module::PluginFinder qw( );
my $finder = Module::PluginFinder->new(
search_path => 'Plugins',
);
my $test = $finder->construct("Plugin1");
$test->run();
答案 3 :(得分: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()
BEGIN {};
此外,Test.pm
模块中import()
更好地放入了这一切。否则{{1}}可能不会生效。
答案 4 :(得分:1)
如果你想对错误做一些特别的事情:
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
...;
}
...;
}
答案 5 :(得分:0)
足够的方法是:
eval "require $plugin_class; 1" or die "Error";
您可以查看现代框架Mojolicious Mojo::Loader
,看看它是如何完成的。