2017-07-28 93 views
-1

我想創建一個C++程序,可以啓動另一個程序並與標準用戶通信。這裏有一個基本的例子: 說,我有任何一種語言的程序A(例如Python的exampe,但它應該是任何一種程序)。該程序通過具有特定命令的控制檯啓動(如「./myprogram.exe」或「python ./myprogram.py」或「java ./myprogram.jar」)。它等待用戶的輸入並給出所有先例輸入的總和。C++程序和未識別程序之間的雙向通信

實施例:

./myprogram.exe 
Please enter a numer. 
User > 4 
4 
User > 2 
6 
User > 9 
15 

因此該方案具有的存儲器。

現在,我要的是使自動化的用戶輸入和輸出一個C程序B.內++讀書所以我的節目B機器會自動發送輸入等待其他程序A到之前給出輸出發送另一個輸入等等...... 沒有關閉並重新啓動程序 A因爲程序A有一個輸入內存。

注意:程序A(已測試)不可更改。我只想對它進行基準測試而不修改它。

你知道我可以如何進行這種溝通嗎?

謝謝

+0

什麼插座? – DimChtz

+0

你想要做什麼基準測試? –

+0

通常的解決方案是從程序B執行程序A並重定向其輸入/輸出。在unix世界中,你可以用'pipe()','fork()','dup2()','read()'和'write()'來做到這一點。 – geza

回答

0

謝謝你的意見,但我讀了pipe()fork()等只有在UNIX環境下工作,我在Windows上工作(對不起,忘了說......)。

因此,經過搜索,找到文檔和創建一些代碼,我終於設法得到我想要的。

警告:我給這個解決方案的人面對同樣的問題,我想要的東西只是爲了工作。它可能並不安全,也可能不是最好的解決方案,請自行承擔風險。請記住它對於Windows非常具體。

#include "iostream" 

#include <windows.h> 
#include <tchar.h> 
#include <stdio.h> 
#include <strsafe.h> 

#define BUFSIZE 4096 

HANDLE g_hChildStd_IN_Rd = NULL; 
HANDLE g_hChildStd_IN_Wr = NULL; 
HANDLE g_hChildStd_OUT_Rd = NULL; 
HANDLE g_hChildStd_OUT_Wr = NULL; 

HANDLE g_hInputFile = NULL; 

using namespace std; 

void CreateChildProcess(string cmdLine); 
void WriteToPipe(string input); 
string ReadFromPipe(); 
void ErrorExit(PTSTR); 


int main() 
{ 
    SECURITY_ATTRIBUTES saAttr; 

    cout << "Starting pipes..." << endl; 

    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL; 

    if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) 
     cout << "Error : StdoutRd CreatePipe" << endl; 

    if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) 
     cout << "Error : Stdout SetHandleInformation" << endl; 

    if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) 
     cout << "Error : Stdin CreatePipe" << endl; 

    if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) 
     cout << "Error : Stdin SetHandleInformation" << endl; 

    cout << "Creating child process..." << endl; 

    CreateChildProcess("python C:/Users/Me/Desktop/Benchmark/test.py"); 

    WriteToPipe("5"); 

    ReadFromPipe(); 
    ReadFromPipe(); 

    getchar(); 

    return 0; 
} 

void CreateChildProcess(string cmdLine) 
{ TCHAR *szCmdline = new TCHAR[cmdLine.size() + 1]; 
    szCmdline[cmdLine.size()] = 0; 
    std::copy(cmdLine.begin(), cmdLine.end(), szCmdline); 

    PROCESS_INFORMATION piProcInfo; 
    STARTUPINFO siStartInfo; 

    ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); 

    ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); 
    siStartInfo.cb = sizeof(STARTUPINFO); 
    siStartInfo.hStdError = g_hChildStd_OUT_Wr; 
    siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; 
    siStartInfo.hStdInput = g_hChildStd_IN_Rd; 
    siStartInfo.dwFlags |= STARTF_USESTDHANDLES; 

    if (!CreateProcess(NULL, szCmdline, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo)) 
    { 
     cout << "Error : CreateProcess" << endl; 
    } 
    else 
    { 
     CloseHandle(piProcInfo.hProcess); 
     CloseHandle(piProcInfo.hThread); 
    } 
} 

void WriteToPipe(string input) 
{ 
    DWORD dwWritten; 
    CHAR chBuf[BUFSIZE]; 

    cout << "> " << input.c_str() << endl; 

    input += "\n"; 

    if (!WriteFile(g_hChildStd_IN_Wr, input.c_str(), strlen(input.c_str()), &dwWritten, NULL)) 
    { 
     cout << "Error : WriteFile" << endl; 
    }  
} 

string ReadFromPipe() 
{ 
    DWORD dwRead, dwWritten; 
    CHAR chBuf[BUFSIZE]; 
    BOOL bSuccess = FALSE; 
    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 

    string output = ""; 
    bool flag = false; 

    for (;;) 
    { 
     bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL); 
     if (!bSuccess || dwRead == 0) break; 

     for (int i = 0; i < dwRead; i++) 
     { 
      if (chBuf[i] == '\n') 
      { 
       flag = true; 
       break; 
      } 
      output += chBuf[i]; 
     } 
     if (flag) 
     { 
      break; 
     } 
    } 

    cout << "< " << output.c_str() << endl; 

    return output; 
} 

而且程序test.py是:

import sys 

sys.stdout.write('Loading module\n') 

test = int(input()) 

sys.stdout.write(str(test+1)) 
sys.stdout.write('\n') 

這將完成是發送字符串 「5 \ n」 來一次test.py和讀取輸出(即 「6」) 。它可以與任何命令一起使用,如java test.jarpython test.pytest.exe

void CreateChildProcess(string cmdLine)允許您使用特定的命令行創建子進程。

void WriteToPipe(string input)讓你送什麼東西給子進程(一個「\ n」是automaticaly添加)

string ReadFromPipe()是同步功能,輸出線的子進程的輸出中的(最後一個字符「\ N」是automaticaly刪除)

該解決方案是部分基於這個有據可查的代碼:https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx

相關問題