Search code examples
c++cross-platformstdiostreamstdio

C++ How can I redirect STDIN to a function


I've spent some time researching for a way to redirect STDOUT and STDIN to functions.

While I eventually found and succeeded at redirecting STDOUT to a callback, I'm unable to redirect STDIN to a callback too (I can't find any resources except for redirecting STDIN to files).

Thanks in advance.

Edit: I made a custom console with windows forms and I've connected it with pipes to my main program. I can already print and read from it using this:

Console::PrintLn("Hello World!");
std::string in;
Console::ReadLn(in);

But my goal was to use for example this:

std::string str;
std::cin >> str; // Read string from custom console
std::cout << str << std::endl; // Print string to custom console
std::printf("Hi!"); // It should also work with printf

Solution

  • So, I don't believe you can do this in a cross-platform way.

    Essentially what you want to do is replace stdin and stdout with something that instead of actually doing input and output, calls your console input and output routines.

    This, mostly, isn't exactly possible. Part of the reason why is that even if you replace stdin and stdout it will not be enough. There may be parts of the program that try to manipulate stdin and stdout in an even more direct fashion.

    On a Unix system I would solve this with threads and pipes or socketpairs. Then I would use the dup2 system call to replace file descriptors 0 and 1. That would make sure that no program could bypass your console unless it tried extremely hard (basically it would have to open /dev/tty and output to that on purpose).

    On Windows, I have no idea what I'd do to solve this problem in a complete way. You could try using freopen, to replace stdin and stdout. That will work for most code because it will use the standard library calls. And cin and cout are supposed to actually use C stdio underneath so that they're interoperable with C code that may be running on another thread.

    I'm not sure if a FILE * in the Visual C/C++ version the stdio library contains anything that would let you redirect IO to callbacks, so you'd probably still have to somehow use the Windows equivalent of pipes to make this work.

    If you just want to replace cout and cin that's probably doable by replacing their streambuf objects with your own. I'm not exactly sure how to make this work, but I think you should look at the rdbuf member functions of the cin and cout objects.

    Implementing your own streambuf isn't hard. I just had to do this myself. Unfortunately, even though the code contains nothing particularly specific to any of the details of what I'm working on here, the code is still proprietary, so I can't paste it. But there are a number of examples of this in the various code samples from a Josuttis book on the C++ standard library.

    For your particular case, you could likely get away with a streambuf of your own that just overloaded the underflow (for input) and overflow (for output) functions and had a completely unbuffered streambuf.