从另一个具有不同 Active perl 版本的 perl 脚本调用 perl 函数
Posted
技术标签:
【中文标题】从另一个具有不同 Active perl 版本的 perl 脚本调用 perl 函数【英文标题】:Call perl function from another perl script with different Active perl versions 【发布时间】:2020-07-18 02:16:49 【问题描述】:我们有两个版本的 Active perl 5.6 和 5.24。我们有必须在 Active perl '5.24' 版本(采用 TLS 1.2 版本)上执行的 Web 服务,这需要从 Active perl '5.6' 版本调用。我们使用的是windows操作系统。
后续步骤: 在 5.6 版本中执行的调用者代码使用 system /require 命令调用 5.24 版本。
问题: 如何通过系统命令、require 等从 5.6 perl 脚本调用 5.24 perl 函数(例如:webservicecall(arg1)return "xyz")? 还有如何获取perl函数5.24的返回值?
注意: 拥有两个 perl 版本是一项临时工作,我们计划将其升级为更高版本。
这里 perl 5.6 版安装在“C:\Perl\bin\perl\”中,perl 5.24 版安装在“D:\Perl\bin\perl\”中。
"**p5_6.pl**"
print "Hello Perl5_6\n";
system('D:\Perl\bin\perl D:\sample_program\p5.24.pl');
print $OUTFILE;
$retval = Mul(25, 10);
print ("Return value is $retval\n" );
"**p5_24.pl**"
print "Hello Perl5_24\n";
our $OUTFILE = "Hello test";
sub Mul($$)
my($a, $b ) = @_;
my $c = $a * $b;
return($c);
我已经编写了示例程序以获取从 perl 脚本 5.6 版本调用 perl 5.24 版本的详细信息。在执行期间,我没有得到预期的输出。如何在 p5_6.pl 脚本中获取 p5_24.pl 的“return $c”值和“我们的 $OUTFILE”值?
注意:以上是基于此的示例程序,我将使用序列化数据修改实际程序。
【问题讨论】:
【参考方案1】:将需要 v5.24 的函数的代码放在一个包装脚本中,编写它以便运行该函数(并打印其结果)。实际上,我建议使用该函数编写一个模块,然后将该模块加载到包装脚本中。
然后在想要的 (5.24) 解释器下运行该脚本,通过其完整路径调用它。 (您可能需要小心确保所有库和环境都是正确的。)这样做的方式可以让您获取其输出。这可以是任何东西,从反引号 (qx
) 到管道打开,或者更好的是,到好的模块。为此有一系列模块,例如IPC::System::Simple
、Capture::Tiny
、IPC::Run3
或IPC::Run
。使用哪个取决于您需要多少通话。
你不能在一个正在运行的程序中调用一个函数,而是让它在另一个程序下运行。
另外,在一个程序中定义的变量(如$OUTFILE
)在另一个程序中是看不到的。您可以从 v5.24 程序中打印它们以及该函数结果,然后在 v5.6 程序中解析整个输出。然后这两个程序需要一些“协议”——要么遵守打印的顺序,要么以某种方式标记打印。
更好的是,编写一个包含需要共享的函数和变量的模块。然后 v5.24 程序可以加载模块并导入它需要的函数并运行它,而 v5.6 程序可以加载相同的模块,但只能获取该变量(并且还运行 v5.24 程序)。
这是所有这一切的草图。打包文件SharedBetweenPerls.pm
package SharedBetweenPerls;
use warnings;
use strict;
use Exporter qw(import);
our @EXPORT_OK = qw(Mul export_vars);
my $OUTFILE = 'test_filename';
sub Mul return $_[0] * $_[1]
sub export_vars return $OUTFILE
1;
然后v5.24程序(下面用program_for_5.24.pl
)就可以了
use warnings;
use strict;
# Require this to be run by at least v5.24.0
use v5.24;
# Add path to where the module is, relative to where this script is
# In our demo it's the script's directory ($RealBin)
use FindBin qw($RealBin);
use lib $RealBin;
use SharedBetweenPerls qw(Mul);
my ($v1, $v2) = @ARGV;
print Mul($v1, $v2);
而v5.6程序可以做到
use warnings;
use strict;
use feature 'say';
use FindBin qw($RealBin);
use lib $RealBin;
use SharedBetweenPerls qw(export_vars);
my $outfile = export_vars(); #--> 'test_filename'
# Replace "path-to-perl..." with an actual path to a perl
my $from_5.24 = qx(path-to-perl-5.24 program_for_5.24.pl 25 10); #--> 250
say "Got variable: $outfile, and return from function: $from_5.24";
其中$outfile
具有字符串test_filename
而$from_5.24
变量是250
。†
如果两个程序和模块都在同一个目录中,并且名称与本示例中的名称相同,则测试它可以正常工作。 (并将path-to-perl-5.24
替换为您的v5.24 可执行文件的实际路径。)如果它们位于不同的位置,您需要调整路径,可能是包名称和use lib
行。见lib pragma。
请注意,有更好的方法来运行外部程序 --- 请参阅上面推荐的模块。所有这些都是粗略的演示,因为许多细节取决于你具体做什么。
最后,程序还可以通过套接字连接并交换所需的一切,但这有点复杂,可能不需要。
† 问题已被编辑,我们现在有D:\Perl\bin\perl
对应path-to-perl-5.24
和D:\sample_program\p5.24.pl
对应program_for_5.24
。
请注意,使用p5.24.pl
程序的这样一个位置,您必须为模块提供一个合适的位置,然后它的名称需要在其中包含(一部分)该路径并被加载有这样的名字。参见例如this post。
没有模块的粗略演示(最初发布)
作为一个非常粗略的草图,在你的 v5.6 下运行的程序中你可以这样做
my $from_5.24 = qx(path-to-perl-5.24 program_for_5.24.pl 25 10);
program_for_5.24.pl
可能类似于
use warnings;
use strict;
sub Mul return $_[0] * $_[1]
my ($v1, $v2) = @ARGV;
print Mul($v1, $v2);
变量$from_5.24
在我的测试中最终成为250
。
【讨论】:
我已经详细分享了我的查询 @Grace 您的示例p5.24.pl
程序需要运行它定义的函数 (Mul
),并打印它想要发送给调用它的任何人的内容。所以你需要print Mul(25,10);
。然后调用 p5.24.pl
程序(来自 v5.6 程序),以便您可以获得它的输出(system
不做的事情),例如 my $ret = qx(path-to-perl-5.24 D:\sample_program\p.5.24.pl)
。 (并从p5.24.pl
程序中删除Hello
的打印:)。或者,让p5.24.pl
在调用p5.24.pl
之后将其结果打印到其他程序可以读取的文件。
@Grace 我在答案末尾添加了一个基本示例
@Grace 已编辑并添加到答案中
@Grace 添加了一行代码来帮助加载模块(到两个程序),以防你不知道该怎么做【参考方案2】:
您不能直接调用使用另一个 Perl 版本运行的 Perl 函数。您需要创建一个显式调用该函数的程序。输入和输出需要显式序列化才能在这两个程序之间传输。
序列化可以使用Data::Dumper
、Storable
或类似方法完成。如果需要较低的性能,您可以调用提供system
功能的程序,并与临时文件或管道共享序列化数据。或者您可以创建一些客户端-服务器架构并与套接字共享序列化数据。后者更快,因为它跳过了另一个进程的重复启动和拆卸,而是保持它运行。
【讨论】:
我已经详细分享了我的查询以上是关于从另一个具有不同 Active perl 版本的 perl 脚本调用 perl 函数的主要内容,如果未能解决你的问题,请参考以下文章
可以将 perl 脚本的执行权限限制为从另一个 perl 脚本调用吗?
从另一个 Perl 脚本内部调用 Perl 搜索和替换命令时不起作用