#確かに、UNIXのシグナルにもああいうのが欲しい
#カーネルレベルのデバッグツールで何かないのかな? 出来ないことはないと思うけれど。
#確かにありそうな気はしますが、知らないんですよねぇ
#カーネルデバッガの機能にあったりするんだろうか
#Windows版のgaucheを使ってまして
(call-with-process-io "mecab -O wakati"
(lambda (in out)
...
を、走らせると、mecab が見つからないと言われます。
'"mecab -O wakati ' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
*** PROCESS-ABNORMAL-EXIT: #<process #<win:process-handle 2248 @0pb97940> "cmd"
inactive> exitted abnormally with exit code 1
mecabには、PATHを通してあり、DOS窓からは問題なくアクセス出来ます。
gosh上から使う場合、何か特別な仕掛けが必要なのでしょうか?
(mecabをフルパス指定しても、同様なエラーでした)
#Mingw 版だとプロセスまわりはほとんど何も使えませんよ。
#Cygwin 版ならたぶん大丈夫だと思います。
#mingw版の問題である可能性がひとつ、
#ドンピシャの、Mingw版でした。
薄々は感じていたんですが、やはりそうですか。
今後の見通しは、いかがなものでしょうか?
#それから、エラーメッセージから推測するに、コマンドシェルcmdが、"mecab -O wakati" 全体をコマンド名と解釈してしまっている可能性がひとつあります
#試しに、(call-with-process-io "mecab" ...) というぐあいにオプション無しで走らせて、それでもmecabが見つからないといわれるか、べつのエラーになるかみてみたらどうでしょう。
#mecabだけにして実験しましたが、同様なエラーでした。
#sys-systemが使えましたので、そちらを検討してみます。
#call-with-process-ioが内部で呼んでいるsys-fork-and-execは、一応mingwへの対応が入っているはずなんですね。
#エラーメッセージからすると、文字列で渡されたのでシェル経由で実行しようとしてこけてる感じがするなあ。
#シェルを経由しない呼び出しにするとどうなりますか?
#(call-with-process-io '("mecab" "-O" "wakati") ...) みたいな呼び出しかたです。
#呼出せるみたいです。
#じゃあcmdに渡すところのエスケープかなんかがうまくいってないんじゃないかな
#テストに通ったためしがなかったので対応してないのかと思ってた…。
#よく見るとエラーメッセージが
#'"ls -a ' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
#だからシェルがメッセージ出してるんですよね。
#ああ、テストもcmd.exe経由呼び出しになってるんだな
#cmd.exe経由の方が古くて、直接呼び出すのが新しいから、古いテストだけ残ってるっぽい
#メッセージからするとなんかダブルクォートが非対称っぽい?
#ほんとだ。
#もともとcmd.exeのクオート規則ってよくわからないんだよね。Windowsはシェルじゃなくて各アプリケーションがコマンドラインをパーズすることになってるから
#でも、アプリケーションに渡されたものを見ると微妙に処理された形跡があることもある。
#確か、設定するとクオート無しでも空白を含むパスを書けるようになったりもしたはず。
#(define (trans str)
(call-with-process-io
'("mecab" "-O" "wakati")
(lambda (in out)
(display (ces-convert str 'utf-8 'sjis) out)
(newline out)
(string-split (ces-convert (read-line in #t) 'sjis) " "))))
(trans "abc123def")
上記を実行すると、エラーは出ないものの、行ったきりになって
帰ってこなくなりました。このコード自体は、bsdで検証済みの
ものです。
#flushされてないんかな。(1) newline outのあとに(flush out)をいれてみる (2) newline outのあとに(close-output-port out)をいれてみる
#ありがちですね。
#(1),(2),(1+2)を試しましたが、効果無しで、結果が返ってきませんでした。
#ふーむ。標準入力の接続がうまくいってないのだろうか
#一応stdin, stdout, stderrのリダイレクトをハンドルするコードは入ってるんだが
#とりあえず原因を切り分けてみましょう
#適当なテキストファイルinput.txtを作っておいて、
#あ、いや、input.txtはいらないか。
#いや、あった方がいいな。
#(run-process '("mecab" "-O" "wakati") :input "input.txt" :output "output.txt" :wait #t) ;=> これが帰ってくるか。帰ってきた場合、output.txtの内容は?
#(let1 p (run-process '("mecab" "-O" "wakati") :input "input.txt" :output :pipe) (read-line (process-output-port p) #t)) ;=> 今度はこれが帰ってくるかどうか。
#(let1 p (run-process '("mecab" "-O" "wakati") :input :pipe :output "output.txt") (display "abc123def\n" (process-input-port p)) (close-output-port (process-input-port p))) ;=> こうした場合、output.txtはどうなるか。
#などなど。
#(run-process '("mecab" "-O" "wakati") :input "input.txt" :output "output.txt" :wait #t) ;=> 返ってきて、結果ファイルには、ちゃんと分解されてました
#そしたらプロセス呼び出しとファイルディスクリプタのリダイレクトは少なくともうまくいってるってことだな
#sys-pipeで作ってるパイプの問題かなあ
#gosh> (use gauche.process)
#<undef>
gosh> (let1 p (run-process '("mecab" "-O" "wakati") :input "input.txt" :output :pipe) (read-line (process-output-port p) #t))
*** ERROR: unbound variable: process-output-port
何か、useしておく必要ありましたっけ?
#あ、それは私が間違えてるっぽい
#process-outputだ。
#cmd のスイッチはクオートしちゃダメらしい。
#d:\My Documents>"cmd" "/c" "ls -l"
'"ls -l' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
#(let1 p (run-process '("mecab" "-O" "wakati") :input "input.txt" :output :pipe) (read-line (process-output-port p) #t)) ;=> プロンプトに帰りますが、結果はなしです
#d:\My Documents>"cmd" /c "ls -l"
total 800331
-rw-r--r-- 1 saito Administrators 615 Jun 3 21:50 16.c
-rw-r--r-- 1 saito Administrators 518 Jun 3 21:00 16.c~
(略)
#shiroさんが示された最後の例は、プロンプトに戻り、output.txtに分解された結果残っていました。
#@齊藤 ああなるほど。すばらしい仕様だ(棒読み)。
#@sakae ふーむ。3番めが動いてるってことは子プロセスに送る方はうまくいってるのかな。子プロセスから読み出すのがおかしいか…けれども両方パイプにするとread-lineでつっかえるんだよな。謎