Creating FILE *s ?

Started by
3 comments, last by smart_idiot 19 years, 2 months ago
Sort of an odd question, and I think the answer is that it can't be done (at least not in a portable method) but I thought I'd see if anybody had any ideas. I'm thinking of writing a generic drop down console, like Quake ond it's ilk have, and I thought that one really good way of (sending data to / getting data from it) it would be to create an C++ istream and ostream (possibly two ostreams) that I could then copy over cin, cout and cerr so that anything sent to / read from them would goto / come from the console (it should do this process wide shouldn't it ?). This I can do, although I don't know what to do about blocking on cin yet. What I'm wondering is whether it is possible to do the same sort of thing in C by creating my own FILE * which I could replace the existing stdout, stderr and stdin and get the data passed to / retrieved from my code. Looking in the standard there doesn't seem to be a way to do this portably. Under POSIX based systems I'd create a set of pipes and use dup2 to place the pipes instead of fd 0-2 but this isn't going to work across different platforms. Any bright ideas or comments ?
Advertisement
I don't know why you want to mess around with std::cout/cin/cerr/clog, what you can do is extend IOStreams library how-ever, there are a number of methods to extending it, one way is to introduce a new stream type, this involves extending from std::basic_streambuf class template implementing and/or overriding a thew virtual member functions you can thus assign them to any exisiting I/O stream but its much more nice to provide new I/O streams to accompany your new streambuf that just involves extending basic_i/o/iostream class templates and passing an instance of your new streambuf to basic_i/o/iostream constructor thats pretty much it basic_i/o/iostream takes care of the rest you may possibily add some new member functions if it makes sense e.g. (i/o)fstream have added member functions open/close etc.
1) Overload an std::streambuf
2) Call rdbuf() on each of the streams.
3) Remember to put everything using said streams in a seperate thread, so they don't block drawing and updating game logic.
4) ???
5) Profit.
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.
Hmmm. Looks like I didn't explain very well.

I know that it is possible to subclass streambuf so that I can create a ostream (or a subclass thereof) that will work for my in-game console and my point was I can then assign it to cout/cerr/clog and anything written to them by anything in the process (my code or external C++ libraries) will magically appear on the in-game console rather than the terminal window from which the game was launched. The only problem was if istreams would get confused if they reached an EOF condition and then later it went away as more data was typed into the console (I don't want cin.getline() to block and reaching an EOF when there isn't data to process is the only way I can see to do this).

The problem is that I don't use C++ very much, I prefer plain C and lots of libraries are written in C, anything that they write to stdout (stderr) would still appear in the terminal window rather than the in-game console. I was wondering if anybody had any ideas about doing the same thing in C. If it was possible to intercept the data written to stdout/err (using the stdio functions like printf) to redirect it, possibly by creating my own FILE structure and overwriting the FILE *s stdin, stdout and stderr. I don't think it's possible but I'd thought I'd ask.

Under Posix based systems I can redirect the first three filedescriptors (0-2) which are linked to stdin, stdout and stderr using pipes and dup2 but it is a bit of a hack to prevent them blocking the main process (i.e. I think I'd have to have a seperate thread or process to read and buffer the data otherwise the first call to printf would hang.). It also wouldn't work on non-Posix systems, one of which is in annoyingly widespread use (i.e. Windows).
Quote:Original post by smart_idiot
3) Remember to put everything using said streams in a seperate thread, so they don't block drawing and updating game logic.


There's also the std::streambuf::in_avail() function to find out how much you can read without it blocking.
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.

This topic is closed to new replies.

Advertisement