Prev: Loading a file into a running image with Swank
Next: Funding/Supporting future Common Lisp infrastructure development
From: Bart W on 16 Dec 2009 16:07 Dear all, I'd like to run an external program (an image conversion program) and give it some binary data (a JPEG image) as standard input, and save the result in a file. I'm using CMUCL 20a, whose manual entry for extensions:run-program at http://common-lisp.net/project/cmucl/doc/cmu-user/extensions.html#toc45 says ---- :input ... If specified as :stream, then the process-input slot contains an output stream. Anything written to this stream goes to the program as input. ---- Now (let ((proc (ext:run-program "/bin/cat" nil :wait nil :input :stream :output "file.jpg"))) (stream-element-type (ext:process-input proc))) prints CHARACTER. So the output stream, to which I'm supposed to write the bytes, is a character stream. So the question is: how do I get the /binary/ input (which I have as an array of unsigned bytes) into the program's input? Any advice appreciated. Bart
From: Raymond Toy on 17 Dec 2009 08:30 Bart W wrote: Bart W wrote: > Dear all, > > I'd like to run an external program (an image conversion program) and > give it some binary data (a JPEG image) as standard input, and save the > result in a file. > > I'm using CMUCL 20a, whose manual entry for extensions:run-program at > http://common-lisp.net/project/cmucl/doc/cmu-user/extensions.html#toc45 > says > > ---- > > :input ... If specified as :stream, then the process-input slot contains > an output stream. Anything written to this stream goes to the program as > input. > > ---- > > Now > > (let ((proc (ext:run-program "/bin/cat" nil > :wait nil > :input :stream > :output "file.jpg"))) > (stream-element-type (ext:process-input proc))) > > prints CHARACTER. So the output stream, to which I'm supposed to write > the bytes, is a character stream. > > So the question is: how do I get the /binary/ input (which I have as an > array of unsigned bytes) into the program's input? > > Any advice appreciated. > > Bart > > > > Dear all, > > I'd like to run an external program (an image conversion program) and > give it some binary data (a JPEG image) as standard input, and save the > result in a file. > > I'm using CMUCL 20a, whose manual entry for extensions:run-program at > http://common-lisp.net/project/cmucl/doc/cmu-user/extensions.html#toc45 > says > > ---- > > :input ... If specified as :stream, then the process-input slot contains > an output stream. Anything written to this stream goes to the program as > input. > > ---- > > Now > > (let ((proc (ext:run-program "/bin/cat" nil > :wait nil > :input :stream > :output "file.jpg"))) > (stream-element-type (ext:process-input proc))) > > prints CHARACTER. So the output stream, to which I'm supposed to write > the bytes, is a character stream. > > So the question is: how do I get the /binary/ input (which I have as an > array of unsigned bytes) into the program's input? Good question. One possible way is to take each byte and use code-char and write out the individual characters (or strings). If you're using the unicode version, be sure *default-external-format* is :latin1 (or :iso8859-1). Or instead of specifying :stream, create a binary stream and pass that as the :input parameter. (Not sure if that will work or not.) Ray
From: Bart Wage on 17 Dec 2009 08:58 >>>>> "Raymond" == Raymond Toy <toy.raymond(a)gmail.com> writes: Raymond> Bart W wrote: >> Dear all, >> >> I'd like to run an external program (an image conversion program) >> and give it some binary data (a JPEG image) as standard input, >> and save the result in a file. >> >> I'm using CMUCL 20a, whose manual entry for >> extensions:run-program at >> http://common-lisp.net/project/cmucl/doc/cmu-user/extensions.html#toc45 >> says >> >> ---- >> >> :input ... If specified as :stream, then the process-input slot >> contains an output stream. Anything written to this stream goes >> to the program as input. >> >> ---- >> >> Now >> >> (let ((proc (ext:run-program "/bin/cat" nil :wait nil :input >> :stream :output "file.jpg"))) (stream-element-type >> (ext:process-input proc))) >> >> prints CHARACTER. So the output stream, to which I'm supposed to >> write the bytes, is a character stream. >> >> So the question is: how do I get the /binary/ input (which I have >> as an array of unsigned bytes) into the program's input? >> Raymond> Good question. One possible way is to take each byte and Raymond> use code-char and write out the individual characters (or Raymond> strings). If you're using the unicode version, be sure Raymond> *default-external-format* is :latin1 (or :iso8859-1). Or Raymond> instead of specifying :stream, create a binary stream and Raymond> pass that as the :input parameter. (Not sure if that will Raymond> work or not.) Hello Raymond, Thanks for the suggestions. Unfortunately, they do not work. As for the first one: (defun in-out (byte-array output-file program &optional arguments) (let ((*default-external-format* :latin1)) (with-input-from-string (input-stream (with-output-to-string (s) (loop for b across byte-array do (write-char (code-char b) s)))) (ext:run-program program arguments :input input-stream :output output-file :if-output-exists :supersede)))) (in-out (kmrcl:read-file-to-usb8-array "binary-input-file") "binary-output-file" "/bin/cat") File binary-output-file is written, but contains quite different bytes than the binary-input-file. As for the second one: I haven't got the code at hand, but I tried it and Lisp complains about not being able to do READ-LINE on a binary stream. Any other suggestions? Surely it must be possible to pass a stream of bytes to a program somehow? Thanks, Bart
From: conrad on 18 Dec 2009 21:37 Bart Wage <b.wage(a)xs4all.nl> writes: > Any other suggestions? Surely it must be possible to pass a stream of > bytes to a program somehow? I have code to do this. It is SBCL specific though but maybe it will help. I had to hack up RUN-PROGRAM.
From: Raymond Toy on 23 Dec 2009 18:39
Bart Wage wrote: > > Any other suggestions? Surely it must be possible to pass a stream of > bytes to a program somehow? Sorry for the delay. I see now that if you specify a stream, cmucl will basically write out the data more or less directly from the string, which contains 16-bit characters. This isn't what we want. run-program needs to be updated somehow. But until then, perhaps some variant of the following will work. I tested it very briefly. (defun in-out2 (byte-array output-file program &optional arguments) (let ((proc (ext:run-program program arguments :input :stream :output output-file :wait nil :if-output-exists :supersede))) (loop for x across byte-array do (write-char (code-char x) (process-input proc))) (close (process-input proc)) (process-close proc))) Ray |