Return variables in real time through programs in c++

I have a program written in c++. I'm looking for how I can catch its values in real time with another c++ program. For example I have in the program something like this:

int main()
{
    int n = 0;
    while (true) {
        cout << n << endl;
        n++;
    }
}

That's simple but represents how my real program works, which gives values to n every few milliseconds. Now I want to catch the n values and store them in a new program at the same time it appears in the command windows.

Upvotes: 1

Views: 824

Answers (1)

Scheff&#39;s Cat
Scheff&#39;s Cat

Reputation: 20141

I made a very simple sample for two processes communicating over a pipe.

As it was my intention to demonstrate it on coliru, I had to put the code for both processes into one program. Whether the program acts as writer or reader is decided by commandline argument. Here, is the source code:

#include <cstdlib>
#include <chrono>
#include <iostream>
#include <string>
#include <thread>

namespace Writer {

int main()
{
  // produce some values
  for (int i = 0; i < 10; ++i) {
    // consume some time e.g. for reading camera
    std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(50));
    // determine position
    const int x = std::rand(), y = std::rand();
    // write values to stream
    std::cout << i << ' ' << x << ' ' << y << '\n';
  }
  // done
  return 0;
}

} // namespace Writer

namespace Reader {

int main()
{
  // consume some values
  for (int i = 0;; ++i) {
    // read values
    int iW, x, y;
    if (!(std::cin >> iW >> x >> y)) break;
    // report values
    std::cout << i << ": " << iW << ", x: " << x << ", y: " << y << '\n';
  }
  // report lost input
  std::cout << "End of input.\n";
  // done
  return 0;
}

} // namespace Reader

int main(int argc, char **argv)
{
  const std::string arg1 = argc == 2 ? argv[1] : "";
  if (arg1 != "-i" && arg1 != "-o") {
    std::cerr << "Usage:\n"
      << "a.out -o ... to start the writer\n"
      << "a.out -i ... to start the reader\n";
    return -1;
  }
  if (arg1 == "-o") return Writer::main();
  else return Reader::main();
}

Compiled and started with:

g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out -o | ./a.out -i

Output:

0: 0, x: 1804289383, y: 846930886
1: 1, x: 1681692777, y: 1714636915
2: 2, x: 1957747793, y: 424238335
3: 3, x: 719885386, y: 1649760492
4: 4, x: 596516649, y: 1189641421
5: 5, x: 1025202362, y: 1350490027
6: 6, x: 783368690, y: 1102520059
7: 7, x: 2044897763, y: 1967513926
8: 8, x: 1365180540, y: 1540383426
9: 9, x: 304089172, y: 1303455736
End of input.

Live Demo on coliru

This is how it works:

  1. main() does nothing else than evaluating the command line argument and calling Reader::main() or Writer::main() (or printing an error if no proper argument could be found).

  2. Writer::main() produces some values (with a delay of 50 ms to make it more exciting/realistic) and writes it to std::cout.

  3. Reader::main() consumes some values which are read from std::cin.

That's it.

The actual magic is how it is called:

./a.out -o | ./a.out -i

I'm not sure what OS and shell is behind coliru but it looks like Linux. (It probably would work on a Windows 10 prompt as well but I'm not that familiar with this. I'm mostly using cygwin64 for such cases as I'm a bash fan.)

It starts ./a.out (the default output of the C++ compiler) in two processes one with arg -o the other with arg -i. Thereby, the pipe symbol | connects the standard output channel of the former to the standard input channel of the latter. (The invention of pipes and this pipe syntax was one of the revolutionary Unix concepts. The inventors wanted to connect tools like garden hoses – I once read somewhere.)

To be fair, I must admit that it was newbie who mentioned this idea in his comment.

Upvotes: 2

Related Questions