doujiao4710 2014-02-17 15:18
浏览 55
已采纳

与控制台应用程序通信

I am a beginner. I have tried to communicate to a chess engine with go's exec package, but it requires me to close the stdin. What I wish to do is to establish a dialogue with the engine.

How do I do that with go?

This is the python implementation of the communication which is pretty much straight forward, can be found at How to Communicate with a Chess engine in Python?

    import subprocess, time

    engine = subprocess.Popen(
    'stockfish-x64.exe',
    universal_newlines=True,
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    )

    def put(command):
    print('
you:
\t'+command)
    engine.stdin.write(command+'
')

    def get():
    # using the 'isready' command (engine has to answer 'readyok')
    # to indicate current last line of stdout
    engine.stdin.write('isready
')
    print('
engine:')
    while True:
        text = engine.stdout.readline().strip()
        if text == 'readyok':
            break
        if text !='':
            print('\t'+text)

    get()
    put('uci')
    get()

put('setoption name Hash value 128')
get()
put('ucinewgame')
get()
put('position startpos moves e2e4 e7e5 f2f4')
get()
put('go infinite')
time.sleep(3)
get()
put('stop')
get()
put('quit')

For simplicity consider this in go:

package main

import ( 
    "bytes"
    "fmt"
    "io"
    "os/exec"
)

func main() {
    cmd := exec.Command("stockfish")
    stdin, _ := cmd.StdinPipe()
    io.Copy(stdin, bytes.NewBufferString("isready
"))
    var out bytes.Buffer
    cmd.Stdout = &out
    cmd.Run()
    fmt.Printf(out.String())
}

The program waits without printing anything. But when I close the stdin the program prints the result, but closing the stdin hinders communication between the engine and go program.

The solution:

package main

    import ( 
        "bytes"
        "fmt"
        "io"
        "os/exec"
        "time"
    )

    func main() {
        cmd := exec.Command("stockfish")
        stdin, _ := cmd.StdinPipe()
        io.Copy(stdin, bytes.NewBufferString("isready
"))
        var out bytes.Buffer
        cmd.Stdout = &out
        cmd.Start()
        time.Sleep(1000 * time.Millisecond)
        fmt.Printf(out.String())
    }
  • 写回答

1条回答 默认 最新

  • douzizang7783 2014-02-17 15:53
    关注

    You should still be able to do this with exec.Command and then with the Cmd methods cmd.StdinPipe(), cmd.StdoutPipe(), and cmd.Start()

    The example in the docs for exec.Cmd.StdoutPipe should be able to get you started: http://golang.org/pkg/os/exec/#Cmd.StdoutPipe

    But in your case, you'd be doing reads and writes from the pipes in a loop. I'd imagine your architecture will look like this loop in a goroutine, passing commands to-and-fro the rest of your code via channels.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥200 uniapp长期运行卡死问题解决
  • ¥15 latex怎么处理论文引理引用参考文献
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?