2011-05-25 41 views
1

我使用Open3的popen2與簡單的C++程序的iostreams進行交互。我的理解是,std :: cin和std :: cout是獨立的,但我有我的popen2塊的IO對象讀/寫調用的順序似乎有所作爲。我的C++程序是:使用Ruby popen2與C++ iostreams交互時的排序問題

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

我的Ruby腳本是:

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

以上工作正常,但如果我的stdin.close之前移動stdout.readlines,紅寶石腳本將掛起。我的意圖是有條件地將\ n寫入標準輸入,如果C++程序首先將expected_string寫入標準輸出,但是我必須先關閉stdin流才能執行readlines。就像我說的,我的理解是這兩個流是獨立的,並且由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 
} 

回答

1

看起來像一個僵局:

  1. 的Ruby腳本呼籲IO::readlines,這將不會返回,直到整個流已讀。
  2. C++程序不會實際終止,直到收到回車。

您可能想要調用IO::readline,它會在接收到每行時返回,或者重新排列這兩個腳本以避免死鎖。

+0

工作。將在原始帖子中編輯解決方案。謝謝。 – wholevinski 2011-05-25 18:58:08

0

這是極有可能的是,你只需要stdout.flush什麼,你希望你的記者採取行動之後。

因爲由#popen設置的管道不是tty,所以它不會默認行緩衝。它會做塊緩衝。您需要強制您的數據流通過在「記錄」邊界上調用#flush以數據報方式進行操作。

此外,請參閱IO#sync=以便自動刷新所有I/O。

+0

我忽略了提及我在使用stdout和stdin IO對象之前已經嘗試刷新並且它仍然表現出相同的行爲。另外值得一提的是,如果我的C++程序只使用其中一個流而不是cin和cout,那麼排序並不重要。 – wholevinski 2011-05-25 17:34:38

+0

流的C++和Ruby兩端可能需要刷新操作。 – DigitalRoss 2011-05-25 17:38:44

+0

所以我添加了'std :: cout.flush();'在我的cout之後添加了C++,並且在stdout.readlines之後添加了stdout.flush並且仍然沒有骰子。我將發佈上面的代碼。 – wholevinski 2011-05-25 17:50:31