代码之家  ›  专栏  ›  技术社区  ›  Herobrine

C++程序和未识别程序之间的双向通信

  •  -1
  • Herobrine  · 技术社区  · 9 年前

    我想创建一个C++程序,可以像标准用户一样启动另一个程序并与之通信。

    以下是一个基本示例: 比如说,我有任何一种语言的程序A(比如说Python,但它应该是任何一种程序)。该程序通过带有特定命令(如“/myprogram.exe”或“python/myprogram.py”或“java/myprogram.jar”)的控制台启动。它等待用户的输入,并给出所有先前输入的总和。

    例子:

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

    所以程序有内存。

    现在,我想要的是在C++程序B中自动化用户输入和输出读取 发送输入 等待另一个程序A给出输出 之前 等等 无需关闭并重新启动程序 A因为程序A有输入存储器。

    注:程序A(已测试)不可更改。我只想在不修改它的情况下对其进行基准测试。

    非常感谢。

    1 回复  |  直到 9 年前
        1
  •  0
  •   Herobrine    9 年前

    谢谢你的建议,但我读到了 pipe() , fork() 等等只在UNIX环境下工作,我在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;
    }
    

    import sys
    
    sys.stdout.write('Loading module\n')
    
    test = int(input())
    
    sys.stdout.write(str(test+1))
    sys.stdout.write('\n')
    

    这将要做的是发送字符串“5”进行测试。py并读取输出(即“6”)。它将与以下任何命令一起工作: java test.jar python test.py test.exe .

    void CreateChildProcess(string cmdLine)

    void WriteToPipe(string input)

    string ReadFromPipe() 是一个同步函数,输出子进程的一行输出(最后一个字符自动删除)

    此解决方案部分基于此文档化代码: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx