เรียกใช้ฟังก์ชัน Perl จากสคริปต์ Perl อื่นที่มีเวอร์ชัน Active Perl ต่างกัน
เรามี Active perl 5.6 และ 5.24 สองเวอร์ชัน เรามีบริการเว็บที่ต้องดำเนินการในเวอร์ชัน Active perl '5.24' (เพื่อใช้เวอร์ชัน TLS 1.2) และสิ่งนี้จำเป็นต้องเรียกใช้จากเวอร์ชัน Active perl '5.6' เรากำลังใช้ระบบปฏิบัติการ windows
ตามขั้นตอน:รหัสผู้โทรซึ่งดำเนินการในเวอร์ชัน 5.6 เรียกใช้เวอร์ชัน 5.24 โดยใช้คำสั่ง system /require
ปัญหา:วิธีเรียกใช้ฟังก์ชัน perl 5.24 (ตัวอย่าง: webservicecall(arg1){return "xyz") จากสคริปต์ perl 5.6 ผ่านคำสั่งระบบ ต้องการ หรืออื่นๆ .. จะรับค่าส่งคืนของฟังก์ชัน 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.24 จากเวอร์ชันสคริปต์ perl 5.6 ในระหว่างการดำเนินการ ฉันไม่ได้รับผลลัพธ์ตามที่คาดไว้ วิธีรับค่า "return $c" & ค่า "$OUTFILE ของเรา" ของ p5_24.pl ในสคริปต์ p5_6.pl
หมายเหตุ:ข้างต้นคือโปรแกรมตัวอย่างตามนี้ ฉันจะแก้ไขโปรแกรมจริงโดยใช้ข้อมูลซีเรียลไลซ์
คำตอบ
วางโค้ดสำหรับฟังก์ชันที่ต้องการ v5.24 ในสคริปต์ตัวตัดคำ ซึ่งเขียนขึ้นเพื่อให้เรียกใช้ฟังก์ชันนั้น (และพิมพ์ผลลัพธ์ออกมา) อันที่จริง ฉันขอแนะนำให้เขียนโมดูลด้วยฟังก์ชันนั้น แล้วโหลดโมดูลนั้นในสคริปต์ตัวตัดคำ
จากนั้นเรียกใช้สคริปต์นั้นภายใต้ล่ามที่ต้องการ (5.24) โดยเรียกใช้ผ่านเส้นทางแบบเต็ม (คุณอาจต้องระมัดระวังเพื่อให้แน่ใจว่าไลบรารีและสภาพแวดล้อมทั้งหมดถูกต้อง) ทำเช่นนี้ในลักษณะที่ช่วยให้คุณสามารถรับเอาต์พุตได้ ซึ่งสามารถเป็นอะไรก็ได้ตั้งแต่ backticks ( qx) ไปจนถึงท่อเปิดหรือดีกว่านั้นไปจนถึงโมดูลที่ดี มีโมดูลมากมายสำหรับสิ่งนี้ เช่นCapture::Tiny, IPC::System::Simple, , 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 ปรากมา
โปรดทราบว่ามีวิธีที่ดีกว่าในการรันโปรแกรมภายนอก --- ดูโมดูลที่แนะนำด้านบน ฉันขอย้ำว่านี่เป็นการสาธิตคร่าวๆเนื่องจากรายละเอียดหลายอย่างขึ้นอยู่กับสิ่งที่คุณทำ
สุดท้าย โปรแกรมยังสามารถเชื่อมต่อผ่านซ็อกเก็ตและแลกเปลี่ยนทุกอย่างที่ต้องการได้ แต่นั่นซับซ้อนกว่าเล็กน้อยและอาจไม่จำเป็น
†คำถามได้รับการแก้ไขแล้ว และตอนนี้เรามีD:\Perl\bin\perlfor path-to-perl-5.24และD:\sample_program\p5.24.plforprogram_for_5.24
โปรดทราบว่าด้วยตำแหน่งดังกล่าวของp5.24.plโปรแกรม คุณต้องหาตำแหน่งที่เหมาะสมสำหรับโมดูล จากนั้นชื่อของมันจะต้องมี (ส่วนหนึ่งของ) เส้นทางนั้นอยู่ในนั้นและต้องโหลดด้วยชื่อดังกล่าว ดูตัวอย่างกระทู้นี้
การสาธิตคร่าวๆ ที่ไม่มีโมดูล (โพสต์ต้นฉบับ)
ในโปรแกรมของคุณที่ทำงานภายใต้ 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ในการทดสอบของฉัน
คุณไม่สามารถเรียกฟังก์ชัน Perl ที่ทำงานด้วย Perl เวอร์ชันอื่นได้โดยตรง คุณจะต้องสร้างโปรแกรมที่เรียกใช้ฟังก์ชันอย่างชัดเจน อินพุตและเอาต์พุตจำเป็นต้องทำให้เป็นซีเรียลไลซ์อย่างชัดเจนเพื่อขนส่งระหว่างสองโปรแกรมนี้
การทำให้เป็นอันดับสามารถทำได้ด้วย หรือ Data::Dumperที่Storableคล้ายกัน หากต้องการประสิทธิภาพที่ต่ำกว่า คุณสามารถเรียกใช้โปรแกรมที่มีฟังก์ชันsystemและแบ่งปันข้อมูลซีเรียลไลซ์กับไฟล์ชั่วคราวหรือไพพ์ หรือคุณสามารถสร้างสถาปัตยกรรมไคลเอนต์เซิร์ฟเวอร์และแบ่งปันข้อมูลซีเรียลไลซ์กับซ็อกเก็ต วิธีหลังเร็วกว่าเนื่องจากข้ามการเริ่มต้นซ้ำๆ และการแยกย่อยของกระบวนการอื่น แต่ให้ทำงานแทน