使用Ruby popen2与C ++ iostream进行交互时的排序问题

时间:2011-05-25 17:13:12

标签: ruby iostream popen

我正在使用Open3的popen2与简单的C ++程序的iostream进行交互。我的理解是std :: cin和std :: cout是独立的,但是我的popen2块的IO对象读/写调用的顺序似乎有所不同。我的C ++程序是:

int main(int argc, char** argv) {
  std::string input;
  std::cout<<"EXECUTE TASK"<<std::endl;
  std::cin>>input;
  std::cout<<"END"<<std::endl;
}

我的红宝石脚本是:

require 'open3'
expected_string = "EXECUTE TASK"
Open3.popen2('~/Sandbox/a.out') { |stdin, stdout|
  stdin.write('\n')
  stdin.close
  results = stdout.readlines
  puts results
}

以上工作正常,但如果我在stdout.readlines之前移动stdin.close,则ruby脚本将挂起。我的意图是如果C ++程序首先将expected_string写入标准输出,则有条件地将\ n写入stdin,但是在执行readlines之前我被迫关闭stdin流。就像我说的那样,我的理解是两个流是独立的,popen2返回的文件描述符看起来也是独立的,为什么这个顺序很重要?

感谢任何帮助。感谢。

我想要完成的全部范围的解决方案(有人可能会发现这有用):

int main(int argc, char** argv) {
    std::string input;

    std::cout<<"1"<<std::endl;
    std::cout<<"2"<<std::endl;
    std::cout<<"3"<<std::endl;
    std::cout<<"4"<<std::endl;
    std::cout<<"5"<<std::endl;
    std::cout<<"EXECUTE TASK"<<std::endl;
    std::cout.flush();
    std::cin>>input;
    std::cout<<"END"<<std::endl;
}


require 'open3'

expected_string = "EXECUTE TASK"
Open3.popen2('~/Sandbox/a.out') { |stdin, stdout|
  found = false
  begin
    while(result = stdout.readline)
      puts result
      if(result.include?(expected_string))
        found = true
        break
      end
    end
  rescue
    raise "Exception caught while reading lines"
  end
  stdin.write('\n')
  stdin.close
}

2 个答案:

答案 0 :(得分:1)

看起来像死锁:

  1. ruby​​脚本调用IO::readlines,在读取整个流之前不会返回。
  2. 在收到回车之前,C ++程序实际上并未终止。
  3. 您可能需要调用IO::readline,它会在收到每行时返回,或重新排序这两个脚本,以便没有死锁。

答案 1 :(得分:0)

在您希望通讯员采取行动后,您很可能只需要stdout.flush

由于#popen设置的管道不是tty,因此不会默认为线路缓冲。它会阻止缓冲。您需要通过在“记录”边界上调用#flush来强制您的流以数据报方式运行。

另外,请参阅IO#sync=了解自动刷新所有I / O的方法。