4

I am trying to write a program that interfaces with the Stockfish chess engine via the command line. I've looked into using pipes and redirecting cin/cout, but the problem is that Stockfish runs its own shell instead of just giving single lines out output, e.g.:

~$ stockfish 
Stockfish 261014 64 by Tord Romstad, Marco Costalba and Joona Kiiski
> go movetime 5000
[output]
...
> quit
~$

I tried the following code (from here) to read execute commands and read them back, but it never finishes when I try to run Stockfish and print the output:

#include <string>
#include <iostream>
#include <stdio.h>

std::string exec(char* cmd) {
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return "ERROR";
    char buffer[128];
    std::string result = "";
    while(!feof(pipe)) {
        if(fgets(buffer, 128, pipe) != NULL)
            result += buffer;
    }
    pclose(pipe);
    return result;
}

int main(void)
{
    std::cout << exec("ls") << std::endl; // this works fine
    std::cout << exec("stockfish") << std::endl; // this never ends

    return 0;
}

My question is, why didn't this work, and how can I write a program that can send and receive text from the Stockfish shell?

Community
  • 1
  • 1

1 Answers1

1

Your while loop will only finish when it detects an EOF on the pipe, and that won't happen until the popen'd command terminates. The fact that it is waiting for input is essentially undetectable.

Since popen has only redirected stdout, the popen'd stockfish shares stdin with your program. When you start stockfish, it will try to read input. If you don't type something, nothing will happen.

So you should try sending stockfish the command(s) you want it to perform, ending with a "quit" command.

Popen only lets you send or receive data, depending on the mode operand. You can never do both. You could do the usual fork and exec technique, or you could popen somethibg like stockfish < sfcmds.txt.

rici
  • 234,347
  • 28
  • 237
  • 341