I want to sent some data from my program to a process executed via uiop:run-program
.
The following works:
(require :asdf)
(asdf:load-system :uiop)
(uiop:with-temporary-file (:stream dot-program-stream
:pathname dot-program-file)
(format dot-program-stream "digraph g { n1 -> n2; }")
(finish-output dot-program-stream)
:close-stream
(uiop:with-temporary-file (:pathname png-data)
(uiop:run-program '("/usr/bin/dot" "-Tpng") :input dot-program-file
:output png-data)
(uiop:launch-program '("/usr/bin/display") :input png-data)))
It seems rather convoluted.
A simpler version, where I used only a stream did not finish-output
and did not use the :close-stream
label resulted in dot
producung an empty 0 byte file.
How to execute a process and pass it data generated by my lisp program as standard input?
Take a closer look at the documentation of uiop:launch-program
and uiop:run-program
, especially the options for the :input
and :output
keys.
You can call launch-program
with :input :stream
. Launch-program
returns a process info object that contains the stream connected to that program's standard input behind the accessor process-info-input
, so you can print to that.
If you have a different program that produces output that should go into that input stream, you have several options:
run-program
with :output :string
for the first call, then use launch-program
with :input :stream
for the second and write the output of the first to that streamlaunch-program
also for the first call, in this case with :output :stream
, then read from that output and print it to the second program's inputYou can either read everything first, then write everything, or you can do buffered reading and writing, which might be interesting for long running processes.
Instead of this in-process buffering, you could also use a fifo (named pipe) from your OS.