Вызов функции perl из другого сценария perl с различными версиями Active perl - PullRequest
2 голосов
/ 06 апреля 2020

У нас есть две версии Active perl 5.6 и 5.24. У нас есть веб-сервисы, которые должны выполняться в версиях Active perl '5.24' (для принятия версии TLS 1.2), и их необходимо вызывать из версии Active perl '5.6'. Мы используем windows операционную систему.

Выполнены следующие шаги: Код вызывающего абонента, который выполняется в версии 5.6, вызывает версию 5.24 с помощью команды system / require.

Проблема: Как вызвать функцию 5.24 perl (пример: webservicecall (arg1) {return "xyz") из скрипта 5.6 perl через системную команду, require или et c ..? Кроме того, как получить возвращаемое значение функции 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» и значение «our $ OUTFILE» для p5_24.pl в скрипте p5_6.pl?

Примечание: Выше приведен пример программы основываясь на этом, я изменю реальную программу, используя сериализованные данные.

Ответы [ 2 ]

4 голосов
/ 06 апреля 2020

Поместите код для функции, которой требуется 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).

Вот эскиз всего этого. Файл пакета 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 может выполнить

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 вам нужно будет найти подходящее местоположение для модуля, а затем его имя должно будет содержать (часть) этот путь в нем и загружаться с таким именем. См., Например, этот пост .


Сырое демо без модуля (изначально опубликовано)

Как очень грубый набросок, в ваша программа, которая работает под 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 в моем тесте.

1 голос
/ 06 апреля 2020

Вы не можете напрямую вызвать функцию Perl, работающую с другой версией Perl. Вам необходимо создать программу, которая явно вызывает функцию. Для переноса между этими двумя программами входные и выходные данные должны быть явно сериализованы.

Сериализация может выполняться с Data::Dumper, Storable или подобным. Если требуется более низкая производительность, вы можете вызвать программу, которая предоставляет функцию с system и поделиться сериализованными данными с временными файлами или каналами. Или вы можете создать архитектуру клиент-сервер и поделиться сериализованными данными с сокетами. Последний работает быстрее, поскольку он пропускает повторный запуск и завершение работы другого процесса, но вместо этого поддерживает его работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...