从另一个具有不同 Active perl 版本的 perl 脚本调用 perl 函数

Call perl function from another perl script with different Active perl versions

我们有两个版本的 Active perl 5.6 和 5.24。我们有必须在 Active perl '5.24' 版本(采用 TLS 1.2 版本)上执行的 Web 服务,这需要从 Active perl '5.6' 版本调用。我们正在使用 windows 操作系统。

遵循的步骤: 在 5.6 版本中执行的调用方代码使用系统 /require 命令调用 5.24 版本。

问题: 如何通过系统命令、要求或等从 5.6 perl 脚本调用 5.24 perl 函数(例如:webservicecall(arg1){return "xyz")? 另外如何获取perl函数5.24的return值?

注: 有两个 perl 版本是暂时的解决方法,我们计划将其升级到更高版本。

"C:\Perl\bin\perl\" 中安装了 perl 5.6 版,"D:\Perl\bin\perl\" 中安装了 perl 5.24 版。

"**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脚本中获取"return $c"值和p5_24.pl的"our $OUTFILE"值?

注:以上是示例程序在此基础上我将使用序列化数据修改实际程序

您不能直接调用 Perl 函数 运行 另一个 Perl 版本。您需要创建一个显式调用该函数的程序。输入和输出需要显式序列化以便在这两个程序之间传输。

可以使用 Data::DumperStorable 或类似的方式进行序列化。如果需要较低的性能,您可以调用提供函数的程序 system 并与临时文件或管道共享序列化数据。或者您可以创建一些客户端-服务器架构并与套接字共享序列化数据。后者更快,因为它跳过了另一个进程的重复启动和拆卸,而是保持它 运行.

将需要 v5.24 的函数的代码放在包装器脚本中,这样编写就可以 运行 执行该函数(并打印其结果)。实际上,我建议编写一个具有该功能的模块,然后在包装脚本中加载该模块。

然后 运行 该脚本在所需的 (5.24) 解释器下,通过其完整路径调用它。 (您可能需要小心确保所有库和环境都是正确的。)以允许您获取其输出的方式执行此操作。这可以是任何东西,从反引号 (qx) 到管道打开,或者更好的是,到好的模块。为此有一系列模块,例如 IPC::System::SimpleCapture::TinyIPC::Run3IPC::Run。使用哪个取决于您需要从该呼叫中获得多少。

您不能在 运行ning 程序中调用函数,而是以某种方式在另一个程序中 运行 调用它。

此外,在一个程序中定义的变量(如 $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

请注意,有更好的方法来 运行 外部程序 --- 请参阅上面推荐的模块。所有这些都是 粗略的演示 ,因为许多细节取决于您的具体操作。

最后,程序还可以通过套接字连接并交换所需的一切,但这有点复杂,可能不需要。


问题已被编辑,现在 path-to-perl-5.24D:\Perl\bin\perlprogram_for_5.24D:\sample_program\p5.24.pl

请注意,对于 p5.24.pl 程序的这样一个位置,您必须为模块提供一个合适的位置,然后它的名称需要包含该路径的(一部分)并加载这样的名称。例如参见 [​​=38=].


没有模块的原始演示(最初发布)

作为一个非常粗略的草图,在您的 运行 低于 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