我正在使用boost.process库在Windows 10上使用Visual Studio 2019。我正在尝试下象棋,并且我将Stockfish引擎用作单独的可执行文件。我需要引擎在游戏的整个过程中都能运行,因为这是设计使用的方式。
当前我在ChessGame.h中
class ChessGame
{
public:
void startStockFish();
void beginGame();
void parseCommand(std::string cmd);
private:
boost::process::child c;
boost::process::ipstream input;
boost::process::opstream output;
}
在ChessGame.cpp中
#include ChessGame.h
void ChessGame::startStockFish()
{
std::string exec = "stockfish_10_x32.exe";
std::vector<std::string> args = { };
boost::process::child c(exec, args, boost::process::std_out > input,
boost::process::std_in < output);
//c.wait()
}
void ChessGame::beginGame()
{
parseCommand("uci");
parseCommand("ucinewgame");
parseCommand("position startpos");
parseCommand("go");
}
void ChessGame::parseCommand(std::string cmd)
{
output << cmd << std::endl;
std::string line;
while (std::getline(input, line) && !line.empty())
{
std::cout << line << std::endl;
}
}
在main.cpp中
ChessGame chessGame = ChessGame(isWhite); //isWhite is a boolean that control who the player is, irrelevent to the question
//std::thread t(&ChessGame::startStockFish, chessGame);
chessGame.startStockFish();
chessGame.beginGame();
问题是我相信函数startStockFish完成后它将终止c,因为如上所述没有任何输出到终端,但是如果我在startStockFish()中使用beginGame(),它将按预期输出。另外,如果我取消注释c.wait()行,并且该功能等待退出stockfish,那么它将陷入困境,因为stockfish永远不会收到exit命令。如果我改为尝试在main中的单独线程上运行startStockFish(如上所示), 出现以下两个错误:
功能测试宏的参数必须是一个简单的标识符。
在文件'boost \ system \ detail \ config.hpp'第51行
和
'std :: tuple :: tuple':没有重载函数带有2个参数。
在文件“内存”第2042行
此外,我也不想使用线程,因为我可以想象这会在输入和输出流中产生自己的问题。
那么,有没有办法让我的进程保持活动状态,或者我需要以其他方式重新组织代码?我相信在main中调用该过程会起作用,但是我真的不想这样做,因为我想将所有与国际象棋有关的代码都保留在ChessGame.cpp中。
答案 0 :(得分:0)
好吧,我相信在c.detach();
中初始化boost.process子级后添加startStockFish()
已经达到了我想要的效果,因为该函数结束时该程序不再终止c
。输入似乎可以与分离的进程一起正常工作,只需编写output << cmd << std::endl;
即可,其中cmd是所需的命令,如std :: string一样没有问题。但是,输出确实存在一些问题,这是
std::string line;
while (std::getline(input, line) && !line.empty())
{
// Do something with line
}
有些有效,但是std::getline(input, line)
将在没有更多行可输出时陷入无限循环。我找不到直接的解决方案,但确实找到了解决方法。
首先,我将boost.process子级的初始化更改为
boost::process::child c(exec, args, boost::process::std_out > "console.txt", boost::process::std_in < output);
,然后将输入更改为文件读取器流std::ifstream
。然后获得我使用的输出
input.open("console.txt");
std::string line;
while (std::getline(input, line))
{
// Do something with line
}
input.close();
我还将remove("console.txt");
添加到startStockFish()
的开头以获取新的文本文件。
我不确定这是否是最好的解决方案,因为我担心如果Stockfish试图在读取输入的同时尝试写入console.txt,会发生什么,但这似乎没有发生或没有发生。如果发生的话,这似乎是一个问题,所以现在这是一个适当的解决方案。