Reputation: 139
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
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.
This is how it works:
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).
Writer::main()
produces some values (with a delay of 50 ms to make it more exciting/realistic) and writes it to std::cout
.
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