Detour cout to custom function - c++

I have made a pretty big program which prints very much information to the screen all the time.
The thing is that I can't be there all the time to read and eventually spot errors. So I came up with the idea to write everything that is printed by cout to a file.
The problem is that, how I already wrote, there are plenty "cout's". Working through the whole code and replacing every cout by a custom function would be very annoying.
Is there a way I how I can "hook" cout to be redirected to a custom function of mine?

You can provide a custom stream buffer via the rdbuf method. Here's an example that redirects cout to a file:
std::ofstream ofs("output");
std::cout.rdbuf(ofs.rdbuf());

You can redirect standard output directly to to file using command line with output redirection
fileneame.exe > log.txt
or
./filename > log.txt
Else use some RAII, something like following:
class Logger
{
std::ofstream filehandle;
std::ostream& myStream;
std::streambuf* mySavedStreambuf;
public:
Logger( std::ostream& oldStream, std::string const& filename)
: filehandle(filename)
, myStream(oldStream)
, mySavedStreambuf(oldStream.rdbuf())
{
oldStream.rdbuf(filehandle.rdbuf());
}
~Logger()
{
myStream.rdbuf(mySavedStreambuf);
}
};
And then in your intilization/main routine do something like:
int main()
{
{
Logger temp( std::cout, "log.txt" );
// call funcs that has std::cout, all outputs will be in log.txt
}// temp goes out of scope, std::cout restored.
// Call funcs that has std::cout, now all outputs on standard ouput.
}

Related

How to redirect stderr/stdout to my log in c++? [duplicate]

This question already has answers here:
Suppress output to cout from linked library
(6 answers)
Closed 7 years ago.
I'm using a 3rd party that sometimes has internal errors, when it happens the 3rd party writes to stderr and I can see it in the console.
(I do check the return values of the 3rd party functions and see that he's failed, but i want the information he writes to stderr)
I have a logger to whom I write using a method I have
SendLog(string log);
I want somehow to catch the things my 3rd party is writing to the stderr (maybe listen on the stderr some how) and then write this things to my log.
How can I do it ?
I need it because my users can't see the console, the only see the log.
It is important to note, my program doesn't crash or exists after those errors, it's continues to work.
EDIT:
My question is not the same as the allegedly similar question, I want to avoid using linker hacks (as been used in the similar question).
One solution is to duplicate everything that is written to cerr into for example a file.
This is the helper class:
class CTee {
public:
// Use ostream &s2 if you want to duplicate to an ostream, pass other
// stuff you need if you have other logging mechanisms.
CTee(ostream &s1, ostream &s2) : m_s1(s1), m_s1OrigBuf(s1.rdbuf()), m_teebuf(s1.rdbuf(), s2.rdbuf()) { s1.rdbuf(&m_teebuf); }
~CTee() { m_s1.rdbuf(m_s1OrigBuf); }
private:
CTee &operator =(CTee &rhs); // not implemented
class CTeeBuf : public streambuf {
public:
// Use streambuf *sb2 if you want to duplicate to an ostream/streambuf.
// Pass other Information if you want to log to something different.
CTeeBuf(streambuf* sb1, streambuf* sb2) : m_sb1(sb1), m_sb2(sb2) {}
protected:
virtual int_type overflow(int_type c) {
if(streambuf::traits_type::eq_int_type(c, streambuf::traits_type::eof()))
return c;
else {
// Put char to cerr/stream to duplicate
m_sb1->sputc((streambuf::char_type)c);
// Put char to duplicate stream. If you want to duplicate to something
// different, then write the char whereever you want to.
return m_sb2->sputc((streambuf::char_type)c);
}
}
virtual int sync() {
m_sb1->pubsync();
return m_sb2->pubsync();
}
// Store streambuf *m_sb2 if you want to duplicate to streambuf.
// Store anything else if you want to duplicate to something different.
streambuf *m_sb1, *m_sb2;
};
ostream &m_s1;
streambuf * const m_s1OrigBuf;
CTeeBuf m_teebuf;
};
CTee takes an ostream to duplicate and an ostream to duplicate to. It takes the ostream that shall be duplicated and replaces it's rdbuf, the streambuf that is written to, with a CTeeBuf (see CTee ctor). CTeeBuf takes the chars that are written to it and forwards them to the streambufs of both ostreams (see CTeeBuf::overflow and CTeeBuf::sync). The CTee dtor reverts the changed streambufs to their original values.
And it is used like this:
char logfilename[] = "myfile.log";
ofstream logfile(logfilename, ios_base::out | ios_base::app);
CTee tee(cerr, logfile);
From now on everything written to cerr will be duplicated to logfile (during the lifetime of tee). So this message will be written to cerr, but also to logfile:
cerr << "error occured: ..." << endl;
It is also possible to write to other ostreams than a logfile. If you don't want to duplicate to another ostream but to something else, just replace CTeeBuf::overflow by an implementation that logs whereever you want to.
See also http://www.cs.technion.ac.il/~imaman/programs/teestream.html and http://wordaligned.org/articles/cpp-streambufs.
One way is to use stringstream for this. If library write using c++streams that will work.
class redirect_stream
{
public:
redirect_stream(std::ostreamstream& stream, std::ostream& oldstream) :
stream_(stream), oldstream_(oldstream)
{
oldbuf_ = oldstream_.rdbuf();
oldstream_.rdbuf(stream_.rdbuf());
}
~redirect_stream()
{
const std::string str = stream_.str();
if (!str.empty())
{
SendLog(str);
}
oldstream_.rdbuf(oldbuf_);
}
private:
std::ostringstream& stream_;
std::ostream& olstream_;
std::streambuf* oldbuf_;
};
And before usage of 3rd party library just:
std::ostringstream oss;
redirect_stream redirecter(oss, std::cerr);
or you can not print message to log in destructor and just print oss.str() after the end of work with 3rd party library.
Simple usage example
You can use std::stringstream
std::stringstream log;
std::streambuf *buf = std::cerr.rdbuf(log).rdbuf());
std::cerr << "Error Msg" << std::endl;
std::string errMsg( log.str() );
errMsg will be "Error Msg".

Writing to both terminal and file c++

I found this question answered for Python, Java, Linux script, but not C++:
I'd like to write all outputs of my C++ program to both the terminal and an output file. Using something like this:
int main ()
{
freopen ("myfile.txt","w",stdout);
cout<< "Let's try this";
fclose (stdout);
return 0;
}
outputs it to only the output file named "myfile.txt", and prevents it from showing on the terminal. How can I make it output to both simultaneously? I use visual studio 2010 express (if that would make any difference).
Thanks in advance!
Possible solution: use a static stream cout-like object to write both to cout and a file.
Rough example:
struct LogStream
{
template<typename T> LogStream& operator<<(const T& mValue)
{
std::cout << mValue;
someLogStream << mValue;
}
};
inline LogStream& lo() { static LogStream l; return l; }
int main()
{
lo() << "hello!";
return 0;
}
You will probably need to explicitly handle stream manipulators, though.
Here is my library implementation.
There is no built in way to do this in one step. You have to write the data to a file and then write the data out on screen in two steps.
You can write a function that takes in the data and the filename and does this for you, to save you time, some sort of logging function.
I have a method to do this, and it is based on a subscriber model.
In this model all your logging goes to a "logging" manager and you then have "subscribers" that decide what to do with the messages. Messages have topics (for me a number) and loggers subscribe to one or more topic.
For your purpose, you create 2 subscribers, one that outputs to the file and one that outputs to the console.
In the logic of your code you simply output the message, and at this level not need to know what is going to be done with it. In my model though you can check first if there are any "listeners" as this is considered cheaper than constructing and outputting messages that will only end up in /dev/null (well you know what I mean).
One way to do this would be to write a small wrapper to do this, for example:
class DoubleOutput
{
public:
// Open the file in the constructor or any other method
DoubleOutput(const std::string &filename);
// ...
// Write to both the file and the stream here
template <typename T>
friend DoubleOutput & operator<<(const T& file);
// ...
private:
FILE *file;
}
To have a class instead of a function makes you use the RAII idiom (https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization)
To use it:
DoubleOutput mystream("myfile");
mystream << "Hello World";

Redirecting cout into same file from various sources in c++

my problem is I have a couple of cout's in various files in the project. I would like all of them to be redirected and saved in .txt file, and what I achieved by now is that only one cout is saved in the file. I don't want to create separate .txt for each cout, for the sake of reading them at once. My code looks now like this:
#include <fstream>
#include <string>
#include <iostream>
int main()
{
std::ofstream out("out.txt");
std::cout.rdbuf(out.rdbuf());
std::cout << "get it3";
std::cout << "get it4";
}
Both cout are in one file, but assuming they are in two different, how to redirect and save in one .txt?
The obvious answer is that you should never output to
std::cout. All actual output should be to an std::ostream&,
which may be set to std::cout by default, but which you can
initialize to other things as well.
Another obvious answer is that redirection should be done before
starting the process.
Supposing, however, that you cannot change the code outputting
to std::cout, and that you cannot control the invocation of
your program (or you only want to change some of the outputs),
you can change the output of std::cout itself by attaching
a different streambuf. In this case, I'd use RAII as well, to
ensure that when you exit, std::cout has the streambuf it
expects. But something like the following should work:
class TemporaryFilebuf : public std::filebuf
{
std::ostream& myStream;
std::streambuf* mySavedStreambuf;
public:
TemporaryFilebuf(
std::ostream& toBeChanged,
std::string const& filename )
: std::filebuf( filename.c_str(), std::ios_base::out )
, myStream( toBeChanged )
, mySavedStreambuf( toBeChanged.rdbuf() )
{
toBeChanged.rdbuf( this );
}
~TemporaryFilebuf()
{
myStream.rdbuf( mySavedStreambuf );
}
};
(You'll probably want to add some error handling; e.g. if you
cannot open the file.)
When you enter the zone where you wish to redirect output, just
create an instance with the stream (std::cout, or any other
ostream) and the name of the file. When the instance is
destructed, the output stream will resume outputting to
whereever it was outputting before.

Redirecting std::cout when program is run as a service

I have a c++ program that prints to the screen using std::cout.
Sometimes I need to run it as a service. Is there any way of seeing the cout outputs when it's running as a Windows service?
Redirecting the output to a file or some sort of debugging program would be ideal.
Obviously I could replace the cout with a function that writes to a file, and that's probably what I'll do, but I'm curious to know if there are other solutions.
There's basically infinite options. The first few that come to mind:
Pass around an ostream reference
You could pass around an std::ostream reference:
void someFunc(std::ostream& out) {
//someFunc doesn't need to know whether out is a file, cout, or whatever
out << "hello world" << std::endl;
}
Replace cout underlying buffer with a file
Example from cplusplus.com:
streambuf *psbuf, *backup;
ofstream filestr;
filestr.open ("test.txt");
backup = cout.rdbuf(); // back up cout's streambuf
psbuf = filestr.rdbuf(); // get file's streambuf
cout.rdbuf(psbuf); // assign streambuf to cout
cout << "This is written to the file";
There's a 1-liner with freopen, but I have a creeping feeling (and this seems to reenforce it in the comments) that it's undefined behavior since stdin and cout can be un-synchronized.
freopen("/path/to/file", "r", stdout);
//cout is now writing to path/to/file
A logging library
Not sure of a good one of the top of my head, but you could go full out and use some type of logging library. (There's also Windows events, though depending on what you're outputting, that might not make sense.)
Piping
I doubt this is possible with a Windows service, but if it is, there's always the classic redirection:
blah.exe > C:\path\file
The easy solution is SetStdHandle(STD_OUTPUT_HANDLE, your_new_handle).
You could do something like this:
class MyTerminal {
std::stringstream terminalText;
}
class MyWindow {
public:
void OnUpdate();
protected:
CTextbox m_textbox;
MyTerminal m_terminal;
}
void MyWindow::OnUpdate()
{
m_textBox.setText(m_terminal.terminalText.str());
m_terminal.terminalText.str(std::string());
}

C++: Redirecting STDOUT

In my application, I want to redirect the output that would normally go to the stdout stream to a function I define. I read that you can redirect stdio to a file, so why not to a function?
For example:
void MyHandler( const char* data );
//<<Magical redirection code>>
printf( "test" );
std::cout << "test" << std::endl;
//MyHandler should have been called with "test" twice, at this point
How can I achieve this / similar behaviour?
#Konrad Rudolph is right, you can totally do this, easily, at least for cout/cerr/clog. You don't even need your own streambuf implementation, just use an ostringstream.
// Redirect cout.
streambuf* oldCoutStreamBuf = cout.rdbuf();
ostringstream strCout;
cout.rdbuf( strCout.rdbuf() );
// This goes to the string stream.
cout << "Hello, World!" << endl;
// Restore old cout.
cout.rdbuf( oldCoutStreamBuf );
// Will output our Hello World! from above.
cout << strCout.str();
Same thing works for cerr and clog, but in my experience that will NOT work for stdout/stderr in general, so printf won't output there. cout goes to stdout, but redirecting cout will not redirect all stdout. At least, that was my experience.
If the amount of data is expected to be small, the freopen/setbuf thing works fine. I ended up doing the fancier dup/dup2 thing redirecting to a pipe.
Update: I wrote a blog post showing the dup2 method I ended up using, which you can read here. It's written for OS X, but might work in other Unix flavors. I seriously doubt it would work in Windows. Cocoa version of the same thing here.
Invoking a callback function whenever something’s written to the underlying standard output stream is hard: it requires overriding low-level, system-specific functions (on POSIX systems, it would require at least overriding write, and the way this is called might depend on the standard library implementation, so it might be different between e.g. glibc and musl).
But depending on what exactly you’re after you can solve this in C++ without resorting to low-level OS specific functions, by manipulating the C++ stream buffers directly.
For this you need to create your own std::streambuf implementation, i.e. your own stream buffer.
Once you have that, you can redirect the std::cout stream by switching the buffer:
auto buf = callback_streambuf(MyHandler);
auto pold_buffer = std::cout.rdbuf(&buf);
std::cout << "Hello" << std::cout;
// Restore original buffer:
std::cout.rdbuf(pold_buffer);
However, what this implementation won’t do is call your callback function exactly twice. Instead, the number of calls will depend on several factors, but it generally will not depend on the number of stream insertions (<<), and there is no way around that!
For the specific example above, the callback is called once, with the data "Hello\n".
The following minimal implementation illustrates how to get a streambuf to call your handler:
class callback_streambuf : public std::streambuf {
public:
callback_streambuf(std::function<void(char const*, std::streamsize)> callback) : callback(callback) {}
protected:
std::streamsize xsputn(char_type const* s, std::streamsize count) {
callback(s, count);
return count;
}
private:
std::function<void(char const*, std::streamsize)> callback;
};
This implementation has several caveats. For instance, it does the wrong thing when attempts are made to use it as an input stream. It doesn’t override overflow (since I don’t think this is ever called, although I find conflicting information about this on the internet; at any rate, adding overflow would be trivial). I didn’t implement synchronisation, so the callback will be called concurrently from multiple threads. Furthermore, there is no error handling, since the callback does not return a success status. I also had to change the signature of the callback to
void MyHandler(char const* data, std::streamsize count);
The second parameter is required since data isn’t a string, it’s a raw char buffer, so there is no way to determine its length intrinsically, and MyHandler can do nothing useful with the data without knowing its length.
Answer: Yes you can, via a dup. freopen will only reopen stdout to a file, as you talked about.
Check out How to buffer stdout in memory and write it from a dedicated thread
It's possible to disable stdin/stdout by dereferencing its pointer:
FILE fp_old = *stdout; // preserve the original stdout
*stdout = *fopen("/dev/null","w"); // redirect stdout to null
HObject m_ObjPOS = NewLibraryObject(); // call some library which prints unwanted stdout
*stdout=fp_old; // restore stdout
The std::cout object has a fixed meaning, and that is to output to the standard out stream. The user of your program gets to control where standard out is connected to, not you. What you can do is decide whether you wish to write to a file, to standard out or to any other output stream. So in your code you switch what stream you write to.
Again, the point of writing to the standard out stream is to give the user a flexibility in choosing where the output goes to. You're not supposed to redirect standard out; this is something the user is supposed to have the freedom to do.
Another thing is that you shouldn't mix C IO and C++ IO in a C++ program. Choose which IO library you wish to work with and stick to it.
That said, you can in C++ quite elegantly switch streams for a function to take input from by templating the handler function on the template parameters of std::basic_istream<>. Then the function will read its input from the input stream independently of the real kind of stream it's working with. Here's an example:
#include<iostream>
#include<fstream>
#include<string>
template<class Ch, class Tr>
void dodge_this(std::basic_istream<Ch, Tr>& in)
{
// in is an input stream. read from it as you read from std::cin.
}
int main(int argc, char* argv[])
{
if( std::string(argv[1]) == "cin" ) {
dodge_this(std::cin);
} else if( std::string(argv[1]) == "file" ) {
std::ifstream file("input.txt");
dodge_this(file);
} else {
dodge_this(dev_null_stream); // i just made that up. you get the idea.
}
}
Another option is to place your handler class calls into the inherited streambuf class. I had a requirement to redirect cout to a Win GUI edit control in a dialog box that may be of some use. Here is the class code:
//-------------------------------- DlgStringbuf Definition -----------------------
class DlgStringbuf : public std::stringbuf
{
public:
DlgStringbuf(void) : _hwndDlg(NULL), _editControlID(0), _accum(""), _lineNum(0) {}
void SetDlg(HWND dlg, int editControlID)
{ _hwndDlg = dlg; _editControlID = editControlID; }
void Clear(void)
{ _accum.clear(); _lineNum = 0; }
protected:
virtual std::streamsize xsputn(const char* s, std::streamsize num)
{
std::mutex m;
std::lock_guard<std::mutex> lg(m);
// Prepend with the line number
std::string str(s, (const uint32_t)num);
str = std::to_string(_lineNum) + ": " + str + "\r\n";
// Accumulate the latest text to the front
_accum = str + _accum;
// Write to the Win32 dialog edit control.
if(_hwndDlg != NULL)
SetDlgItemTextW(_hwndDlg, _editControlID, (LPCWSTR)(std::wstring(_accum.begin(), _accum.end())).c_str());
_lineNum++;
return(num);
}//end xsputn.
private:
std::string _accum;
HWND _hwndDlg;
int _editControlID;
uint32_t _lineNum;
};//end DlgStringbuf.
//-------------------------------- DlgStream Definition ------------------------------
class DlgStream : public std::ostream
{
public:
DlgStream(void) : std::ostream(&_sbuff) {}
void SetDlg(HWND dlg, int editControlID)
{ _sbuff.SetDlg(dlg, editControlID); }
void Clear(void)
{ _sbuff.Clear(); }
private:
DlgStringbuf _sbuff;
};
...and in the WinMain, someplace after the dialog box and its edit control is created:
// Redirect all cout usage to the activity dlg box.
// Save output buffer of the stream - use unique pointer with deleter that ensures to restore
// the original output buffer at the end of the program.
auto del = [&](streambuf* p) { cout.rdbuf(p); };
unique_ptr<streambuf, decltype(del)> origBuffer(cout.rdbuf(), del);
// Redirect the output to the dlg stream.
_dlgStream.SetDlg(hwndActivityDlg, IDC_EDIT_ACTIVITY);
_dlgStream.copyfmt(cout);
cout.rdbuf(_dlgStream.rdbuf());
cout << "this is from cout";
You can use sprintf to write to a character array and then read the value:
char buf[1024];
sprintf(buf, "test");
MyHandler(buf);
there are also snprintf and a few others depending on platform