Perl中如何通过STDIN/STDOUT与另一个程序进行交互并启动它?

4

我有一个C程序,它简单地运行一个循环,从STDIN读取JSON结构并将一行写入STDOUT。

为了支持各种前端格式,我想编写一个Perl程序,重复读取数据,将其转换为JSON,提交给C程序,并接收输出--就像使用qx//调用C程序一样,但不需要每次都重新启动。

这个线程描述了相同的问题,只不过父进程是C。我想知道Perl是否提供了更容易的方法来实现这个。如果可能的话,最好(但不是必须的)让C程序保持不变,无论是由Perl分叉还是从命令行运行,都不知道自己被分叉了。

为了说明(注意-在子进程中使用Perl,但希望相同的原则适用):

文件parent.pl

#!/usr/bin/env perl 
use warnings;
use strict;
$|++;

# {{ spawn child.pl }}
while (1) {
    print "Enter text to send to the child: ";
    my $text = <>;
    last if !defined $text;
    # {{ send $text on some file descriptor to child.pl }}
    # {{ receive $reply on some file descriptor from child.pl }}
}

文件 child.pl:

#!/usr/bin/env perl 
use warnings;
use strict;
$|++;
while (my $line = <STDIN>) {
    chomp $line;
    $line .= ", back atcha.\n";
    print $line;
}

执行:

$ parent.pl
Enter text to send to the child: hello
hello, back atcha.
Enter text to send to the child: 

更新:

使用open2时需要注意的注意事项,如下面的@ikegami所述和Programming Perl / Interprocess Communication中所述,我认为在这里不适用,因为:

  • 我不关心STDERR(这需要open3select
  • 我控制子代码,并且可以保证自动刷新发生。
  • 协议严格是发送一行,接收一行。

如何表示请求的结束?如何表示响应的结束?子进程的输出是否真正无缓冲? - ikegami
请求和响应都是由以\n结尾的一行文本组成。而$|++是否能保证子进程的换行符终止的行会被刷新呢? - Chap
1个回答

3

考虑到原问题中的这些条件...

  • 您不关心读取 STDERR 输出
  • 您控制子进程源代码,因此可以保证自动刷新。
  • 协议严格遵循发送一行,接收一行。

...以下内容有效。(请注意,此处子进程使用Perl编写,但也可以使用C语言。)

parent.pl

#!/usr/bin/env perl 
use warnings;
use strict;
use IPC::Open2;
$|=1;
my $pid = open2(my $ifh, my $ofh, 'child.pl') or die;
while (1) {
    print STDOUT "Enter text to send to the child: ";
    my $message = <STDIN>;
    last if !defined $message;
    print $ofh $message;   # comes with \n
    my $reply = <$ifh>;
    print STDOUT $reply;
}
close $ifh or die;
close $ofh or die;
waitpid $pid, 0;

child.pl

#!/usr/bin/env perl 
use warnings;
use strict;
$|=1;

while (my $line = <STDIN>) {
    chomp $line;
    print STDOUT $line . ", back atcha.\n";
}

没错,那样可以。只要确保在接收到上一个请求的响应之前不要发送另一个请求。 - ikegami

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接