0

I have an console application 'app.exe', which i want to invoke from a C++ program and then communicate with it as if it was a command line. Essentially I want to make a C++ wrapper around another console application so that I could pass input to it at will and receive output.

In pseudo-code something like:

std:string input("...some parameters..."), output;
Process app("app.exe");
app.InputOutput(input, output);
std::cout<<output;

This must have been answered already, but I seem to lack proper terminology to look it up.

In case it matters, I am running Eclipse CDT on Windows 10 with GCC 5.3.0

EDIT: I need to be able to repeatedly send some values to 'app.exe' and repeatedly receive response, rather than just invoke it with parameters. This is needed for a small personal project so I do not care about it being platform-specific.

2
  • Terminology: try "windows c++ pipe stdout". You want spawn a process and redirect its stdout to a pipe.
    – jdigital
    Commented Sep 24, 2016 at 23:30
  • This code might give you a useful starting point. It only receives output from the child process (it can't send input) but it could be modified to do so in a hopefully obvious way. Commented Sep 25, 2016 at 23:08

2 Answers 2

1

I used this code as a starting point, in an MFC dialog, to display output from a called process. It was rather painless as this is well documented. He tells you why he is doing what. It should be suitable as you are working with the Windows platform. But as Alf points out, cross platform is something else.

*UPDATE The link to Microsofts answer. And this with the code

Even Better! And sehe should get the credit. In a nut shell...

This is the child process.

#include <iostream>
#include <chrono>
#include <thread>

int main() {
    using namespace std::chrono_literals;
    std::string str;
    int i{};
    for (;;) {
        std::this_thread::sleep_for(600ms);
        if (i++ > 4)
            break;
        str = "test: " + std::to_string(i);
        std::cout << str << std::endl;
    }
    return 0;
}

Be sure to use std::endl in the child so the stream gets flushed. Then...

#include <boost/process.hpp>
#include <boost/asio.hpp>
#include <boost/process/async.hpp>
#include <iostream>
#include <iomanip>

int main() {
    namespace bp = boost::process;
    boost::asio::io_context context;
    bp::async_pipe out(context);

    //correct this path to point to your 'process.exe'
    bp::child c(R"(D:\cpp\stack_test\Debug\process.exe)", bp::std_out > out, context);

    std::vector<std::string> lines;

    boost::asio::streambuf buffer;

    std::function<void()> read_loop;
    read_loop = [&] {
        boost::asio::async_read_until(out, buffer, "\n", [&](boost::system::error_code code, std::size_t size) {
            if (!code) { //good to go
                std::cerr << "received: " << size << " bytes" << std::endl;
                auto b = buffers_begin(buffer.data()), m = b + size;
                std::string in(b, m);
                std::cout << in;
                lines.emplace_back(b, m);
                buffer.consume(size);
                read_loop();
            }
            else {
                std::cerr << "Oops: " << code.message() << std::endl;
            }
        });
    };
    read_loop();
    context.run();

    for (auto& line : lines) {
        std::cout << line;
    }

    return c.exit_code();
}

If you don't want context.run() to block, put it in a thread and work it like this in the main loop.

0

You can use the system function to invoke a shell (command line) command.

That command can be to execute a program with the arguments you want.

system returns the process exit code, but for other results there is no direct support. One easy way to access the output, for a program that just does a job and ends, is to redirect the program's output to a file.

Otherwise you'll have to use communication mechanisms such as pipes or Windows mailslots, that are not supported by the C++ standard library, i.e. you're then into platform-specific code.

Not the answer you're looking for? Browse other questions tagged or ask your own question.