|
|
ru.perl- RU.PERL ---------------------------------------------------------------------- From : Artem Chuprina 2:5020/400 24 Mar 2003 16:01:36 To : Mikhail Polykovsky Subject : Re: Re[4]: eval -------------------------------------------------------------------------------- Здравствуй, Mikhail Polykovsky. AC>> Здравый подход заключается в том, чтобы поделить две части. А именно: AC>> eval "use $module ($sub)"; AC>> if ($@) { обработка ошибки } AC>> ${"${module}::our_var1"} = $var1; AC>> ${"${module}::our_var2"} = $var2; AC>> $out .= &$sub($var3); MP> Спасибо, попробую. AC>> Возможно, еще придется поиграться с no strict 'refs', если мы под use AC>> strict. MP> СтоИт. Hе процитирован. AC>> Hо скорее всего, эта задача свидетельствует об ошибке проектирования этого AC>> места. MP> С этого места пожалуйста поподробнее, если не трудно... Характерный способ добыть нужную функцию из нужного модуля (без учета обработки ошибок) - sub dyn_function { my ($module, $sub) = @_; eval "require $module"; return $module->can($sub); } Возвращает указатель на функцию, то есть интерфейс к этому имеет вид dyn_function($module,$sub)->(@args); То есть задача изощрений вокруг eval - получить указатель на функцию модуля, предварительно при необходимости его загрузив. При этом это будет честная reference, а не symbolic. Hа практике, естественно, поступается несколько хитрее, особенно когда это частая операция: our %DynSeen; sub dyn_function { my ($function_name,$module_name) = @_; confess "function is not specified" unless $function_name; confess "module name is not specified" unless $module_name; confess "module name '$module_name' is insecure" unless $module_name =~ /^([ a-zA-Z0-9_:]+)$/; my $module = $1; confess "function name '$function_name' is insecure" unless $function_name = ~ /^([a-zA-Z0-9_]+)$/; my $function = $1; if (!exists $DynSeen{$module}) { # try to load module eval "require $module"; if ($@) { my $mod_fn = $module.'.pm'; $mod_fn =~ s#::#/#g; $mod_fn = quotemeta($mod_fn); cluck "$@" if $@ !~ /^Can't locate $mod_fn in \@INC/; $DynSeen{$module} = ''; } else { $DynSeen{$module} = {}; } } return undef unless $DynSeen{$module}; return $module->can($function); } Проверки из работающего кода движка, причем работающего местами под taint check. Позволю себе не объяснять детали - если надо, следует таки разобраться во всем, что тут лежит в основе. Ключевые слова для perldoc - perltaint и UNIVERSAL. -- Artem Chuprina RFC2822: <ran@ran.pp.ru>, FIDO: 2:5020/122.256, ICQ: 13038757 --- ifmail v.2.15dev5 * Origin: Leninsky 45 home network (2:5020/400) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.perl/1147791a56465.html, оценка из 5, голосов 10
|