On Thursday 06 May 2004 04:41 am, Wiggins d Anconia wrote: [snip] > Generally when I hit an unrecognized warning it is time to check the > perldiag docs, > > perldoc perldiag > > Conveniently, > > "Variable "%s" will not stay shared > (W closure) An inner (nested) named subroutine is referencing a lexical > variable defined in an outer subroutine. > > When the inner subroutine is called, it will probably see the value of > the outer subroutine's variable as it was before and during the *first* > call to the outer subroutine; in this case, after the first call to the > outer subroutine is complete, the inner and outer subroutines will no > longer share a common value for the variable. In other words, the > variable will no longer be shared. > > Furthermore, if the outer subroutine is anonymous and references a > lexical variable outside itself, then the outer and inner subrou > tines will never share the given variable. This problem can usually > be solved by making the inner subroutine anonymous, using the "sub {}" > syntax. When inner anonymous subs that reference variables in outer > subroutines are called or referenced, they are automatically rebound to > the current values of such variables." >
Thank you Wiggins, But maybe I could explain the overall picture. I am trying to embed 'any' script (whthout modification) in perl; I use a perl package (which is run via a c program) to maintain 'persistence' of the script which is read from disk. This must be done in the mod_perl registry for cgi scripts, but my search of the mod_perl source so far has been fruitless. Suppose this script (ev1.pl) is read from disk: #!/usr/bin/perl use strict; use warnings; my $arg1 = shift @ARGV; my $arg2 = shift @ARGV; show_stuff(); sub show_stuff { print "$arg1 and $arg2\n"; } Standalone, this runs fine. Now my perl package (listed at the end), maintains a cache of scripts that have been read from disk, If a script has not yet been seen (tne generated package name for the script is not in the cache), a package name is generated from the script file name and it makes a package of it as follows: package Embed::ev1_2epl; sub __handler__ { shift; @ARGV = @_; my $code = sub { #!/usr/bin/perl use strict; use warnings; my $arg1 = shift @ARGV; my $arg2 = shift @ARGV; show_stuff(); sub show_stuff { print "$arg1 and $arg2\n"; } }; &$code; } An 'eval' of the above statement is done to 'compile' it and the package name is saved a cache. Next the script is 'run' using the package name generated (either a package just compiled or from the cache): eval {$package->__handler__(@user_args);}; is done. Same problem (of course - because as you pointed out it has a nested subroutine issue) : $ perl t1.pl ev1.pl is package Embed::ev1_2epl Variable "$arg1" will not stay shared at (eval 1) line 13. Variable "$arg2" will not stay shared at (eval 1) line 13. jack and jill already compiled Embed::ev1_2epl jack and jill Sorry all, I know this is a bit much... Aloha => Beau; 'persistent' perl package (Embed::Persistent) and test code follows. It is a knock-off of the sample in the perlembed man page. t1.pl: #!/usr/bin/perl package Embed::Persistent; use strict; use warnings; our %Cache; sub valid_package_name { my($string) = @_; $string =~ s/([^A-Za-z0-9\/])/sprintf("_%x",unpack("C",$1))/eg; $string =~ s|/(\d)|sprintf("/_%x",unpack("C",$1))|eg; $string =~ s|/|::|g; $string = "::$string" unless $string =~ /^::/; return "Embed" . $string; } sub _eval_file { my ($filename, @user_args) = @_; my $package = valid_package_name ($filename); my $mtime = -M $filename; if(defined $Cache{$package}{mtime} && $Cache{$package}{mtime} <= $mtime) { print "already compiled $package\n"; } else { local *FH; open FH, $filename || die; my $sub = do { local $/; <FH>; }; close FH; my @chunks = split "(\n__END__)", $sub; $sub = shift @chunks; my $end = join( "", @chunks ) || ''; my $eval = "package $package; sub __handler__ { shift; [EMAIL PROTECTED] = [EMAIL PROTECTED]; my \$code = sub { $sub \n}; &\$code; } \n$end"; print $eval; print "$filename is package $package\n"; my $cmpl_error = do { my($filename,$mtime,$package,$sub); @_ = @user_args; eval $eval; $@; }; die "perl compile error in $filename: $cmpl_error\n" if $cmpl_error; $Cache{$package}{mtime} = $mtime; } my $eval_error = $@ = do { eval {$package->__handler__(@user_args);}; $@; }; die "perl run-time error in $filename: $eval_error\n" if $eval_error; } 1; Embed::Persistent::_eval_file( 'ev1.pl', 'jack', 'jill' ); Embed::Persistent::_eval_file( 'ev1.pl', 'william', 'mary' ); -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>