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

时间:2017-07-28 15:05:51

标签: c++ communication

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

这是一个基本的例子: 比方说,我有任何一种语言的程序A(例如Python,但它可以是任何类型的程序)。该程序通过具有特定命令的控制台启动(例如" ./ myprogram.exe"或" python ./myprogram.py"或" java ./myprogram.jar& #34)。它等待用户的输入并给出所有先前输入的总和。

示例:

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

所以程序有一个记忆。

现在,我想要的是自动化用户输入和C ++程序B中的输出读数。所以我的程序B将自动发送输入等待其他程序A到在发送另一个输入之前提供输出等等...... 不关闭并重新启动程序 A因为程序A有一个输入内存。

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

你知道如何进行这种沟通吗?

谢谢

1 个答案:

答案 0 :(得分: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')

这将做的是发送字符串&#34; 5 \ n&#34; test.py并读取输出(&#34; 6&#34;)。它适用于java test.jarpython test.pytest.exe等任何命令。

void CreateChildProcess(string cmdLine)允许您使用特定命令行创建子进程。

void WriteToPipe(string input)允许您向子进程发送任何内容(&#39; \ n&#39;是自动添加的)

string ReadFromPipe()是一个同步函数,它输出子进程输出的一行(最后一个字符&#39; \ n&#39;被自动删除)

此解决方案部分基于这个记录良好的代码:https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx