IPC
The IPC
library provides various functions for
Inter-Process Communications, and child process handling.
The library functions are called using the library name IPC
and the name of the function. E.g., use
>> IPC::popen("echo coucou", "r")
to read line by line the output of a shell command. This mechanism
avoids naming conflicts with other library functions.
If this is found to be inconvenient, then the routines of the
IPC
library may be exported via export
. E.g., after
calling
>> export(IPC, popen)
the function IPC::popen
may be called directly:
>> popen("echo coucou", "r")
All the routines of the IPC
library are
exported simultaneously by
>> export(IPC)
The functions and sub-libraries available in the
IPC
library can be listed using
>> info(IPC)
In this section, we pick a few sample applications at random.
First, we export
the IPC
library
to save us some typing:
>> export(IPC):
In our first example, we run a shell command, and read the output line by line:
>> child := popen("echo coucou1; echo coucou2", "r"):
getline(child);
getline(child);
getline(child);
close(child):
"coucou1" "coucou2"
Note that there is no output for the last call to getline. Indeed, after the end of output, getline returns null().
We redo the same thing, but at a lower level. Accessing directly
the streams is a little bit faster if efficiency is at a
premium. This is also required if one wants to read from the
standard error stream of the child slave::stderr(child)
:
>> child := popen("echo coucou1; echo coucou2", "r"):
pid := slave::pid(child):
childout := slave::stdout(child):
getline(childout);
getline(childout);
getline(childout);
close(childout):
waitpid(pid):
"coucou1" "coucou2"
We demonstrate how to run some computations in a separate MuPADprocess:
>> child := popen2("mupad -S -P pew"):
putline(child, "setuserinfo(NIL):"):
putline(child, "fprint(Unquoted, 0, 1+1):"):
text2expr(getline(child));
putline(child, "fprint(Unquoted, 0, 7!):"):
text2expr(getline(child));
putline(child, "fprint(Unquoted, 0, expand((x+1)^7)):"):
text2expr(getline(child));
close(child):
2 5040 2 3 4 5 6 7 7 x + 21 x + 35 x + 35 x + 21 x + 7 x + x + 1
This allow for some basic parallelism on a multi-processor machine, or on several machines by using ssh.
Here we run some computations with GAP:
>> child := popen2("gap -b -q -n"):
putline(child, "1+1;"):
text2expr(getline(child));
putline(child, "G := Group((1,2,3,4));"):
getline(child):
putline(child, "Size(G);"):
text2expr(getline(child));
putline(child, "IsSolvable(G);"):
getline(child);
2 4 "true"
To conclude, we show how to create and use a very crude maple slave. Of course, this hack is not robust to errors, and only simple expressions can be manipulated. But in some easy cases this can still be useful.
>> domain maple
child :=
proc()
local child;
begin
child := IPC::popen2("maple -q");
IPC::putline(child, "kernelopts(printbytes=false):");
child;
end_proc();
childin := IPC::slave::stdin(dom::child);
childout := IPC::slave::stdout(dom::child);
new :=
proc(e: DOM_STRING): DOM_STRING
begin
IPC::putline(dom::childin, "lprint(".e."):");
return(IPC::getline(dom::childout));
end_proc;
begin
end:
maple("1+1");
text2expr(maple("expand((1+x)^7)"))
"2" 2 3 4 5 6 7 1 + 7 x + 21 x + 35 x + 35 x + 21 x + 7 x + x
MuPAD Combinat, an open source algebraic combinatorics package