首页 > 解决方案 > 在函数之外保持 boost.process 活着被调用

问题描述

我正在使用 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 永远不会获得退出命令。如果我尝试在 main 中的单独线程上运行 startStockFish(如上所示),则会收到以下两个错误:

功能测试宏的参数必须是一个简单的标识符。
在文件 'boost\system\detail\config.hpp' 第 51 行

'std::tuple::tuple':没有重载函数需要 2 个参数。
在文件“内存”第 2042 行

另外,我不想使用线程,因为我可以想象输入和输出流会有自己的问题。

那么有没有办法让我在这个函数之外保持进程活跃,还是我需要以其他方式重新组织我的代码?我相信在 main 中调用该过程会起作用,但我真的不想这样做,因为我想将所有与国际象棋相关的代码保留在 ChessGame.cpp 中。

标签: c++boost

解决方案


好的,我相信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 时会发生什么,因为输入正在从中读取,但这似乎没有发生或似乎没有发生如果它已经发生,那就是一个问题,所以现在它是一个适当的解决方案。


推荐阅读