在不同perl版本下运行的程序之间传递对象

在不同perl版本下运行的程序之间传递对象,perl,serialization,Perl,Serialization,将对象作为输入参数从perl5.6.pl传递到perl5.24.pl时遇到问题(无法从函数“$from_5.24”获取返回值)。下面提供了有问题的代码。使用windows平台,如何解决这个问题 在perls.pm之间共享: package SharedBetweenPerls; use warnings; use strict; use Exporter; our @ISA = 'Exporter'; our @EXPORT_OK = qw(getVal); sub new { my $

将对象作为输入参数从perl5.6.pl传递到perl5.24.pl时遇到问题(无法从函数“$from_5.24”获取返回值)。下面提供了有问题的代码。使用windows平台,如何解决这个问题

在perls.pm之间共享:

package SharedBetweenPerls;
use warnings;
use strict;
use Exporter;
our @ISA = 'Exporter';
our @EXPORT_OK = qw(getVal);

sub new {
   my $self = {
      roleId => undef,
      username => undef,
   };
   bless $self, 'SharedBetweenPerls';
   return $self;
}

sub getVal{
  my ($self) = @_;
  return $self->{'roleId'};
}
1;
use warnings;
use strict;
use v5.24;
use lib '.';
my ($self) = @_;
print $self->{'roleId'}; # Not working
use warnings;
use strict;
use lib '.'; 
use SharedBetweenPerls;

my $obj =  new SharedBetweenPerls();
$obj->{'roleId'} = '10000';
$obj->{'username'} = 'test123';

my $roleId = $obj->getVal();
print "Value : $roleId \n"; # working fine

my $from_5.24 = qx(path-to-perl-5.24 program_for_5.24.pl "$obj"); 
print "Return from function: $from_5.24"; # Not Working
use warnings;
use strict;
use lib '.'; 
use SharedBetweenPerls;
use IPC::System::Simple qw(capturex);
#my $data = '{"roleId":31, "username":"test123"}';
#my $obj = SharedBetweenPerls->new($data);
my $obj = SharedBetweenPerls->new(roleId => 17, username => 'test123');
my $result = capturex('D:\Perl\bin\perl524.exe', 'D:\sample_program\p5.24.pl', '$obj->serialize');
print "return from function: $result";
use warnings;
use strict;
use v5.24;
use lib '.';
use SharedBetweenPerls;
my ($init_json) = @ARGV;
my $obj = SharedBetweenPerls->new( $init_json );
print $obj->{'roleId'};
v5.24.pl:

package SharedBetweenPerls;
use warnings;
use strict;
use Exporter;
our @ISA = 'Exporter';
our @EXPORT_OK = qw(getVal);

sub new {
   my $self = {
      roleId => undef,
      username => undef,
   };
   bless $self, 'SharedBetweenPerls';
   return $self;
}

sub getVal{
  my ($self) = @_;
  return $self->{'roleId'};
}
1;
use warnings;
use strict;
use v5.24;
use lib '.';
my ($self) = @_;
print $self->{'roleId'}; # Not working
use warnings;
use strict;
use lib '.'; 
use SharedBetweenPerls;

my $obj =  new SharedBetweenPerls();
$obj->{'roleId'} = '10000';
$obj->{'username'} = 'test123';

my $roleId = $obj->getVal();
print "Value : $roleId \n"; # working fine

my $from_5.24 = qx(path-to-perl-5.24 program_for_5.24.pl "$obj"); 
print "Return from function: $from_5.24"; # Not Working
use warnings;
use strict;
use lib '.'; 
use SharedBetweenPerls;
use IPC::System::Simple qw(capturex);
#my $data = '{"roleId":31, "username":"test123"}';
#my $obj = SharedBetweenPerls->new($data);
my $obj = SharedBetweenPerls->new(roleId => 17, username => 'test123');
my $result = capturex('D:\Perl\bin\perl524.exe', 'D:\sample_program\p5.24.pl', '$obj->serialize');
print "return from function: $result";
use warnings;
use strict;
use v5.24;
use lib '.';
use SharedBetweenPerls;
my ($init_json) = @ARGV;
my $obj = SharedBetweenPerls->new( $init_json );
print $obj->{'roleId'};
v5.6.pl:

package SharedBetweenPerls;
use warnings;
use strict;
use Exporter;
our @ISA = 'Exporter';
our @EXPORT_OK = qw(getVal);

sub new {
   my $self = {
      roleId => undef,
      username => undef,
   };
   bless $self, 'SharedBetweenPerls';
   return $self;
}

sub getVal{
  my ($self) = @_;
  return $self->{'roleId'};
}
1;
use warnings;
use strict;
use v5.24;
use lib '.';
my ($self) = @_;
print $self->{'roleId'}; # Not working
use warnings;
use strict;
use lib '.'; 
use SharedBetweenPerls;

my $obj =  new SharedBetweenPerls();
$obj->{'roleId'} = '10000';
$obj->{'username'} = 'test123';

my $roleId = $obj->getVal();
print "Value : $roleId \n"; # working fine

my $from_5.24 = qx(path-to-perl-5.24 program_for_5.24.pl "$obj"); 
print "Return from function: $from_5.24"; # Not Working
use warnings;
use strict;
use lib '.'; 
use SharedBetweenPerls;
use IPC::System::Simple qw(capturex);
#my $data = '{"roleId":31, "username":"test123"}';
#my $obj = SharedBetweenPerls->new($data);
my $obj = SharedBetweenPerls->new(roleId => 17, username => 'test123');
my $result = capturex('D:\Perl\bin\perl524.exe', 'D:\sample_program\p5.24.pl', '$obj->serialize');
print "return from function: $result";
use warnings;
use strict;
use v5.24;
use lib '.';
use SharedBetweenPerls;
my ($init_json) = @ARGV;
my $obj = SharedBetweenPerls->new( $init_json );
print $obj->{'roleId'};
我已经尝试使用zdim提供的序列化测试代码(SharedBetweenPerls.pm)。我有以下格式错误

malformed JSON string, neither tag, array, object, number, string or atom, at character offset 0 (before "roleId") at SharedBetweenPerls.pm
5.6.pl:

package SharedBetweenPerls;
use warnings;
use strict;
use Exporter;
our @ISA = 'Exporter';
our @EXPORT_OK = qw(getVal);

sub new {
   my $self = {
      roleId => undef,
      username => undef,
   };
   bless $self, 'SharedBetweenPerls';
   return $self;
}

sub getVal{
  my ($self) = @_;
  return $self->{'roleId'};
}
1;
use warnings;
use strict;
use v5.24;
use lib '.';
my ($self) = @_;
print $self->{'roleId'}; # Not working
use warnings;
use strict;
use lib '.'; 
use SharedBetweenPerls;

my $obj =  new SharedBetweenPerls();
$obj->{'roleId'} = '10000';
$obj->{'username'} = 'test123';

my $roleId = $obj->getVal();
print "Value : $roleId \n"; # working fine

my $from_5.24 = qx(path-to-perl-5.24 program_for_5.24.pl "$obj"); 
print "Return from function: $from_5.24"; # Not Working
use warnings;
use strict;
use lib '.'; 
use SharedBetweenPerls;
use IPC::System::Simple qw(capturex);
#my $data = '{"roleId":31, "username":"test123"}';
#my $obj = SharedBetweenPerls->new($data);
my $obj = SharedBetweenPerls->new(roleId => 17, username => 'test123');
my $result = capturex('D:\Perl\bin\perl524.exe', 'D:\sample_program\p5.24.pl', '$obj->serialize');
print "return from function: $result";
use warnings;
use strict;
use v5.24;
use lib '.';
use SharedBetweenPerls;
my ($init_json) = @ARGV;
my $obj = SharedBetweenPerls->new( $init_json );
print $obj->{'roleId'};
5.24.pl:

package SharedBetweenPerls;
use warnings;
use strict;
use Exporter;
our @ISA = 'Exporter';
our @EXPORT_OK = qw(getVal);

sub new {
   my $self = {
      roleId => undef,
      username => undef,
   };
   bless $self, 'SharedBetweenPerls';
   return $self;
}

sub getVal{
  my ($self) = @_;
  return $self->{'roleId'};
}
1;
use warnings;
use strict;
use v5.24;
use lib '.';
my ($self) = @_;
print $self->{'roleId'}; # Not working
use warnings;
use strict;
use lib '.'; 
use SharedBetweenPerls;

my $obj =  new SharedBetweenPerls();
$obj->{'roleId'} = '10000';
$obj->{'username'} = 'test123';

my $roleId = $obj->getVal();
print "Value : $roleId \n"; # working fine

my $from_5.24 = qx(path-to-perl-5.24 program_for_5.24.pl "$obj"); 
print "Return from function: $from_5.24"; # Not Working
use warnings;
use strict;
use lib '.'; 
use SharedBetweenPerls;
use IPC::System::Simple qw(capturex);
#my $data = '{"roleId":31, "username":"test123"}';
#my $obj = SharedBetweenPerls->new($data);
my $obj = SharedBetweenPerls->new(roleId => 17, username => 'test123');
my $result = capturex('D:\Perl\bin\perl524.exe', 'D:\sample_program\p5.24.pl', '$obj->serialize');
print "return from function: $result";
use warnings;
use strict;
use v5.24;
use lib '.';
use SharedBetweenPerls;
my ($init_json) = @ARGV;
my $obj = SharedBetweenPerls->new( $init_json );
print $obj->{'roleId'};
注意下面有两种序列化方法——使用
可存储的
(如果它需要在不同的Perl版本和模块版本之间,则可能命中或未命中),以及自定义方法


这是在中提出的问题的更一般的情况,现在在程序之间传递对象。这一变化带来了实质性的差异

一个对象必须是可传递的,这样我们就可以通过某种管道逐字节传递它。我在这个演示中使用了这个工具,但是您可能需要寻找其他工具,或者编写一个自定义流程(在最后添加的部分中演示)

下面将讨论一些其他调整,以下是文件

在perls.pm之间共享

package SharedBetweenPerls;    
use warnings;
use strict;

sub new {
    my ($class, %args) = @_; 
    my $self = { %args };
    return bless $self, $class;
}

sub get_roleId {
    my ($self) = @_; 
    return $self->{'roleId'};
}

1;
需要在v5.24下运行的程序(
v.5.24.pl

“main”程序,必须在较旧的perl下运行

use warnings;
use strict;
use feature 'say';

use Storable qw(store);

use FindBin qw($RealBin); 
use lib $RealBin;   
use SharedBetweenPerls;

my $obj = SharedBetweenPerls->new(roleId => 17, username => 'test123');

my $roleId = $obj->get_roleId();
say "Value for 'roleId' in the new object: $roleId";

my $outfile = "obj_$$.storable";  # store the serialized object in a file
store($obj, $outfile) // warn "There were errors: $!";                 #/

# (replace my perlbrew path with your actual path to the v5.24 executable)
my $perl_524 = qq($ENV{HOME}/perl5/perlbrew/perls/perl-5.30.0/bin/perl);
my $cmd = qq($perl_524 v5.24.pl $outfile);
my $from_524 = qx( $cmd );
chomp $from_524;    
say "Return from function: $from_524";

unlink $outfile or warn "Can't unlink $outfile: $!";  # can delete file now
将序列化对象写入的文件的名称应该比我在本演示中使用的名称好得多,并且是处理临时名称的标准选择

这张照片

Value for 'roleId' in the new object: 17 Return from function: 17 然后,
v.5.24.pl
程序就可以

my ($init_json) = @ARGV;

my $obj = SharedBetweenPerls->new( $init_json );
因此,现在目标程序有了一个用所需数据构建的对象,可以开始工作了

这是一个非常基本和粗糙的例子请注意,对于您的项目,这可能是一个糟糕的选择,我对此一无所知,但如果可以使用,则需要更多的工作/检查。

我使用JSON序列化属性及其值的散列;这是通过
serialize
方法完成的。然后,这样的JSON字符串可以用来构造一个新对象:构造函数检查它是得到了hashref还是字符串,对于字符串,它调用一个方法(
init\u from\u JSON
)来初始化对象

sub new {                     # WARNING: a sketchy demo only
    my ($class, $args) = @_; 
    my $self = {}; 
    bless $self, $class;
    my $ref = ref $args;
    if (not $ref) {                    # a string; better be JSON
        $self->init_from_json($args);
    }   
    elsif ($ref eq 'HASH') {           # straight-up attributes, initialize
        $self->{$_} = $args->{$_}  for keys %$args;
    }   
    else { croak "Unsupported invocation..." }  # print user message etc
    return $self;
}

sub serialize {
   my $self = shift;
    require JSON; JSON->import('encode_json');
    my %attr = map { $_ => $self->{$_} } keys %$self;
    return encode_json(\%attr);  # (no objects please)
}

sub init_from_json {
    my ($self, $args_json) = @_; 
    require JSON; JSON->import('decode_json');
    my $args = decode_json($args_json);
    $self->{$_} = $args->{$_} for keys %$args;
}

...
现在,
v5.6.pl
程序可以创建它的对象并将其序列化,然后调用
v5.30.pl
程序,并将JSON字符串作为输入传递给它。然后,
v5.30.pl
程序可以从JSON重建对象,并使用它进行工作

根据具体情况,还有许多其他方法可以做到这一点

如果要使用面向对象代码的框架,如
Moose
Moo
,那么有现成的工具和技术可以提供帮助。(如果您没有使用这些框架,那么也会有一些学习曲线。)


按照要求,完成工作程序(最大限度地简化以帮助调试)-

v5.6.pl

use warnings;
use strict;
    
use IPC::System::Simple qw(capturex);

use FindBin qw($RealBin); 
use lib $RealBin;   
use SharedBetweenPerls;

my $obj = SharedBetweenPerls->new( { roleId => 17, data => [3..7] } );

# (replace my perlbrew path with your actual path to the v5.24 executable)
my $perl_524 = qq($ENV{HOME}/perl5/perlbrew/perls/perl-5.30.0/bin/perl);

my $from_524 = capturex( $perl_524, 'v5.30.pl', $obj->serialize );
print "Return from function: $from_524";
use warnings;
use strict;

use v5.24;
use FindBin qw($RealBin); 
use lib $RealBin;   
use SharedBetweenPerls;

my ($init_json) = @ARGV;

my $obj = SharedBetweenPerls->new($init_json);
print $obj->get_roleId;
v5.30.pl

use warnings;
use strict;
    
use IPC::System::Simple qw(capturex);

use FindBin qw($RealBin); 
use lib $RealBin;   
use SharedBetweenPerls;

my $obj = SharedBetweenPerls->new( { roleId => 17, data => [3..7] } );

# (replace my perlbrew path with your actual path to the v5.24 executable)
my $perl_524 = qq($ENV{HOME}/perl5/perlbrew/perls/perl-5.30.0/bin/perl);

my $from_524 = capturex( $perl_524, 'v5.30.pl', $obj->serialize );
print "Return from function: $from_524";
use warnings;
use strict;

use v5.24;
use FindBin qw($RealBin); 
use lib $RealBin;   
use SharedBetweenPerls;

my ($init_json) = @ARGV;

my $obj = SharedBetweenPerls->new($init_json);
print $obj->get_roleId;

sub存在于解释器中。这包括方法。因此类也存在于解释器中。对象是类的实例,因此传输对象需要传输类,除非它已加载到要传输对象的解释器中。由于您之前已明确表示不能这样做,因此无法传输对象。请您分享将对象从一个perl版本传输到另一个perl版本的可行性。我刚才解释过,除非您可以在两个解释器中加载类模块,否则无法传输。你能做到吗?你能解释一下如何在两个解释器中加载类模块吗?将对象从5.6传输到5.24的原因是调用支持TLS 1.2的web服务,并且输出需要从5.24传输到5.6。在当前程序中,相同的对象用于输入和输出模块。No。管道只能传输字节序列,我们使用字符串表示字节序列。其他形式的数据需要由发送方序列化(转换为字节序列)并由接收方反序列化。参见zdim的回答,评论不用于扩展讨论;这段对话已经结束。