I have a C program that simply runs a loop that reads a JSON structure from STDIN and writes a line to STDOUT.
In order to support a variety of front-end formats, I want to write a Perl program that repeatedly reads data, converts it to JSON, submits it to the C program, and receives the output -- as if I were using qx// to invoke the C program, only without launching it afresh each time.
This thread describes the same problem, except the parent process is in C. I wondered whether Perl provided a way to do this more easily. It would be preferable (but not essential) for the C program to stay the same and be unaware whether it was forked by Perl or run from the command line, if possible.
To illustrate (note - using Perl for the child, but hopefully the same principles apply):
File 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 }} } File child.pl:
#!/usr/bin/env perl use warnings; use strict; $|++; while (my $line = <STDIN>) { chomp $line; $line .= ", back atcha.\n"; print $line; } Execution:
$ parent.pl Enter text to send to the child: hello hello, back atcha. Enter text to send to the child: UPDATE:
The caveats for using open2, stated both by @ikegami below and in Programming Perl / Interprocess Communication, don't seem to me to apply here, given:
- I don't care about STDERR (which would require
open3andselect) - I control the child source code and can therefore guarantee that autoflushing occurs.
- The protocol is strictly send one line, receive one line.
\n. And doesn't$|++guarantee that the child's newline-terminated line will get flushed?