从具有不同Active Perl版本的另一个Perl脚本中调用Perl函数 [英] Call perl function from another perl script with different Active perl versions

查看:108
本文介绍了从具有不同Active Perl版本的另一个Perl脚本中调用Perl函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有两个版本的Active perl 5.6和5.24。我们提供的网络服务必须在Active perl的 5.24版本(采用TLS 1.2版本)上执行,并且需要从Active perl的 5.6版本中调用。我们正在使用Windows操作系统。



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



问题:
如何调用5.24 perl函数(例如:webservicecall(arg1){返回 xyz )从5.6 perl脚本通过系统命令,require等。
还如何获得perl函数5.24的返回值?



注意:
有两个Perl版本,我们计划将其升级为更高版本。



此处在 C:\Perl\bin\中安装了perl 5.6版perl\和安装在 D:\Perl\bin\perl\中的perl版本5.24。

   ** p5_6.pl ** 

打印 Hello Perl5_6\n;
系统( D:\Perl\bin\perl D:\sample_program\p5.24.pl);

打印$ OUTFILE;
$ retval = Mul(25,10);
打印(返回值为$ retval\n);

** p5_24.pl **

打印 Hello Perl5_24\n;
我们的$ OUTFILE =你好测试;
sub Mul($$)
{
my($ a,$ b)= @_;
我的$ c = $ a * $ b;
return($ c);
}

我编写了示例程序以获取详细信息,以从perl脚本调用perl 5.24版本5.6版本。执行期间,我没有得到预期的输出。如何获得返回$ c值和p5_6.pl脚本中p5_24.pl的我们的$ OUTFILE值?



注意:以上是基于此的示例程序我将使用序列化的数据修改实际程序。

解决方案

将需要v5.24的函数的代码放入包装脚本中,只是为了使其能够运行该功能(并打印其结果)而编写。实际上,我建议使用该功能编写一个模块,然后将该模块加载到包装脚本中。



然后在所需的(5.24)解释器下运行该脚本,方法是通过其完整路径调用它。 (您可能需要注意确保所有库和环境都正确。)以允许您拾取其输出的方式执行此操作。从反引号( qx )到管道打开,或者更好的是,好的模块都可以。有许多用于此的模块,例如 Capture :: Tiny IPC :: System :: Simple IPC :: Run3 IPC :: Run 。使用哪个将取决于您需要从该调用中获取多少。



您不能在正在运行的程序中调用某个函数,而要使其以某种方式在另一个程序下运行



此外,在一个程序中定义的变量(如 $ OUTFILE )在另一个程序中看不到。您可以从v5.24程序中打印它们以及该函数结果,然后在v5.6程序中解析整个输出。然后,这两个程序将需要一个协议,以遵循打印事物的顺序或以某种方式对打印进行标记。



好得多,编写一个包含需要共享的函数和变量的模块。然后,v5.24程序可以加载该模块并导入所需的功能并运行它,而v5.6程序可以加载相同的模块,但只能选择该变量(并运行v5.24程序)。 / p>

以下是所有内容的草图。软件包文件 SharedBetweenPerls.pm

 软件包SharedBetweenPerls; 

使用警告;
使用严格;

使用Exporter qw(import);
我们的@EXPORT_OK = qw(Mul export_vars);

我的$ OUTFILE = test_filename;

sub Mul {return $ _ [0] * $ _ [1]}

sub export_vars {return $ OUTFILE}

1;

然后v5.24程序就可以做到

 使用警告; 
使用严格;

#要求至少由v5.24.0运行
使用v5.24;

#添加相对于该脚本所在位置的模块位置的路径
#在我们的演示中,这是脚本的目录($ RealBin)
使用FindBin qw($ RealBin) ;
使用lib $ RealBin;

使用SharedBetweenPerls qw(Mul);

my($ v1,$ v2)= @ARGV;

打印Mul($ v1,$ v2);

而v5.6程序可以做到

 使用警告; 
使用严格;
使用功能说;

使用FindBin qw($ RealBin);
使用lib $ RealBin;

使用SharedBetweenPerls qw(export_vars);

我的$ outfile = export_vars(); #-> 'test_filename'

#将 path-to-perl ...替换为perl的实际路径
my $ from_5.24 = qx(path-to-perl-5.24 program_for_5 .24.pl 25 10); #-> 250

说 Got变量:$ outfile,并从函数返回:$ from_5.24;

其中 $ outfile 具有字符串 test_filename ,而 $ from_5.24 变量为 250



如果两个程序和模块都位于同一目录中,且名称与本示例中所示相同,则此方法可以按原样测试。 (并且将路径到perl-5.24 替换为v5.24可执行文件的实际路径,无论它在哪里。)如果它们位于不同的位置,则需要调整路径,可能是程序包名称和 use lib 行。请参见 lib编译指示



请请注意,有更好的方法来运行外部程序---请参见上面推荐的模块。我想强调一下,这是一个原始演示,因为许多细节取决于您的工作。



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






该问题已被编辑,现在我们有 D:\Perl\ bin\perl 获取 -perl-5.24 D:\sample_program\p5.24的路径。 pl 表示 program_for_5.24



请注意,使用 p5.24.pl 程序的此类位置,您必须想出模块的合适位置,然后它的名称将需要在其中包含该路径(的一部分)并使用该名称加载。参见例如这篇文章






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



作为一个非常粗略的草图,在v5.6下运行的程序中,您可以

  my $ from_5.24 = qx(到perl-5.24的路径program_for_5.24.pl 25 10); 

其中, program_for_5.24.pl 然后可能类似于

 使用警告; 
使用严格;

sub Mul {return $ _ [0] * $ _ [1]}

my($ v1,$ v2)= @ARGV;

打印Mul($ v1,$ v2);

,变量 $ from_5.24 结束在我的测试中是 250


We have two versions of Active perl 5.6 and 5.24. We have web services which has to be executed on Active perl '5.24' versions(to adopt TLS 1.2 version) and this needs to be invoked from Active perl '5.6' version. We are using windows operating system.

Steps followed : Caller code which is executed in 5.6 version invokes the 5.24 version using system /require command.

Problem: How to call the 5.24 perl function(example: webservicecall(arg1){return "xyz") from 5.6 perl script through system command, require or etc..? Also how to get the return value of perl function 5.24?

Note: Its a temporary work around to have two perl versions and the we have a plan to do upgrade it for higher version.

Here perl version 5.6 installed in "C:\Perl\bin\perl\" and perl version 5.24 installed in "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);
}

I have written sample program for detail information to call perl 5.24 version from perl script 5.6 version. During execution I didn't get the expected output. How to get the "return $c" value & the "our $OUTFILE" value of p5_24.pl in p5_6.pl script?

Note: The above is the sample program based on this I will modify the actual program using serialized data.

解决方案

Place the code for the function that needs v5.24 in a wrapper script, written just so that it runs that function (and prints its result). Actually, I'd recommend writing a module with that function and then loading that module in the wrapper script.

Then run that script under the wanted (5.24) interpreter, by invoking it via its full path. (You may need to be careful to make sure that all libraries and environment are right.)   Do this in a way that allows you to pick up its output. That can be anything from backticks (qx) to pipe-open or, better, to good modules. There is a range of modules for this, like Capture::Tiny, IPC::System::Simple, IPC::Run3, or IPC::Run. Which to use would depend on how much you need out of that call.

You can't call a function in a running program but to have it somehow run under another program.

Also, variables (like $OUTFILE) defined in one program cannot be seen in another one. You can print them from the v5.24 program, along with that function result, and then parse that whole output in the v5.6 program. Then the two programs would need a little "protocol" -- to either obey an order in which things are printed, or to have prints labeled in some way.

Much better, write a module with functions and variables that need be shared. Then the v5.24 program can load the module and import the function it needs and run it, while the v5.6 program can load the same module but only to pick up that variable (and also run the v5.24 program).

Here is a sketch of all this. The package file 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;

and then the v5.24 program can do

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);

while the v5.6 program can do

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";

where $outfile has the string test_filename while $from_5.24 variable is 250.

This is tested to work as it stands if both programs, and the module, are in the same directory, with names as in this example. (And with path-to-perl-5.24 replaced with the actual path to your v5.24 executable, wherever that it is.) If they are at different places you need to adjust paths, probably the package name and the use lib line. See lib pragma.

Please note that there are better ways to run an external program --- see the recommended modules above. May I emphasize that this is a crude demo since many details depend on what exactly you do.

Finally, the programs can also connect via a socket and exchange all they need but that is a bit more complex and may not be needed.


The question's been edited, and we now have D:\Perl\bin\perl for path-to-perl-5.24 and D:\sample_program\p5.24.pl for program_for_5.24.

Note that with such a location of the p5.24.pl program you'd have to come up with a suitable location for the module and then its name would need to have (a part of) that path in it and to be loaded with such name. See for example this post.


A crude demo without a module (originally posted)

As a very crude sketch, in your program that runs under v5.6 you could do

my $from_5.24 = qx(path-to-perl-5.24 program_for_5.24.pl 25 10);

where the program_for_5.24.pl then could be something like

use warnings;
use strict;

sub Mul { return $_[0] * $_[1] }

my ($v1, $v2) = @ARGV;

print Mul($v1, $v2);

and the variable $from_5.24 ends up being 250 in my test.

这篇关于从具有不同Active Perl版本的另一个Perl脚本中调用Perl函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆