How to redirect std::out & std::err to a qDebug() message
-
wrote on 1 Sept 2023, 08:56 last edited by
In my application I use dDebug for logging. Actually I miss all std::out and std::err messages - coming from external libs/dlls/frameworks - in my logging. Is there a way to catch std::out and std::error messages and create a qDebug() message?
I want to do it this way, because all my qDebug() messages ending up in a log file already and I want to add std::err and std::out to it.
I searched the forum but found only logging to file examples.
-
In my application I use dDebug for logging. Actually I miss all std::out and std::err messages - coming from external libs/dlls/frameworks - in my logging. Is there a way to catch std::out and std::error messages and create a qDebug() message?
I want to do it this way, because all my qDebug() messages ending up in a log file already and I want to add std::err and std::out to it.
I searched the forum but found only logging to file examples.
wrote on 1 Sept 2023, 09:02 last edited by@ademmler
I presume you mean nothing to do with running external processes viaQProcess
, you mean that code you link with writes stuff to stdout/err?
Start by confirming that if you run under Qt Creator debugger you do see these messages in its *Application Output pane?
The first thing is that solution will depend on whether your Qt program is a console or a UI application?
You might also indicate target platform(s)? -
@ademmler
I presume you mean nothing to do with running external processes viaQProcess
, you mean that code you link with writes stuff to stdout/err?
Start by confirming that if you run under Qt Creator debugger you do see these messages in its *Application Output pane?
The first thing is that solution will depend on whether your Qt program is a console or a UI application?
You might also indicate target platform(s)? -
@JonB Dear John, thx agin.
yes I meant linked code, which writes stuff to stdout/err.
And yes I see all messages in the debugger.
It is a UI Application running on Mac OS, Windows and Linux - hence cross platform.wrote on 1 Sept 2023, 09:15 last edited by JonB 9 Jan 2023, 09:20@ademmler said in How to redirect std::out & std::err to a qDebug() message:
hence cross platform
Yeah, that's nasty but rules out e.g. any Windows-only solutions, so we know where we are.
Basically I would expect you to use either
freopen(stdout/stderr)
or possiblyopen/dup(1/2)
. These are C library calls, hopefully POSIX, you'd have to check across platforms. You won't be able to actually useqDebug()
, you are trying to getting them into the Qt message handler you must have installed for your present save to log file. Unless you choose to directly append those messages to file rather than go through a Qt message handler, you will probably want to redirect to a string buffer. I don't know whether the C++ at https://en.cppreference.com/w/cpp/io/basic_ios/rdbuf could be useful. -
In my application I use dDebug for logging. Actually I miss all std::out and std::err messages - coming from external libs/dlls/frameworks - in my logging. Is there a way to catch std::out and std::error messages and create a qDebug() message?
I want to do it this way, because all my qDebug() messages ending up in a log file already and I want to add std::err and std::out to it.
I searched the forum but found only logging to file examples.
wrote on 1 Sept 2023, 12:17 last edited by -
wrote on 1 Sept 2023, 13:34 last edited by
@Pl45m4
That is all standardqDebug()
/qInstallMessageHandler()
stuff. I presume the OP already has thatbecause all my qDebug() messages ending up in a log file already and I want to add std::err and std::out to it.
The part the OP wants is how to grab anything written to stdout/err by anything in his application, including from libraries, so code for that cannot be changed.
-
wrote on 1 Sept 2023, 19:53 last edited by
@Pl45m4 Yes I have seen this. Thanks you.
I use this in my Application. This way Uni Messages and Logging goes the same way. Now I wan't to add stderr/out to exit the same logfile.
void MyApplication::sendMessage(QString message, int msg_mode = msg_debug, int seconds) { QFile *file = new QFile; file->setFileName(logFolder.absolutePath() + "/application.log"); file->open(QIODevice::Append | QIODevice::Text); QTextStream logfile(file); logfile.setCodec("UTF-8"); switch (msg_mode) { case msg_debug: qDebug() << message; logfile << "Debug: " << message << "\n"; break; case msg_status: qDebug() << message; logfile << "Status: " << message << "\n"; ui->statusBar->showMessage(message, seconds); break; case msg_boxInfo: qDebug() << message; logfile << "Info: " << message << "\n"; QMessageBox::information(this, tr("Info"), message); break; case msg_boxWarning: qDebug() << message; logfile << "Warning: " << message << "\n"; QMessageBox::warning(this, tr("Warning"), message); break; case msg_boxError: qDebug() << message; logfile << "Error: " << message << "\n"; QMessageBox::warning(this, tr("Error"), message); break; case msg_boxStatus: qDebug() << message; logfile << "Warning: " << message << "\n"; ui->statusBar->showMessage(message, seconds); QMessageBox::warning(this, tr("Warning"), message); break; case msg_boxWarningYN: qDebug() << message; logfile << "Warning: " << message << "\n"; QMessageBox::warning(this, tr("Warning"), message, QMessageBox::Yes | QMessageBox::No); break; } if (file != 0) file->close(); }
-
@Pl45m4
That is all standardqDebug()
/qInstallMessageHandler()
stuff. I presume the OP already has thatbecause all my qDebug() messages ending up in a log file already and I want to add std::err and std::out to it.
The part the OP wants is how to grab anything written to stdout/err by anything in his application, including from libraries, so code for that cannot be changed.
-
wrote on 1 Sept 2023, 23:03 last edited by
@ademmler said in How to redirect std::out & std::err to a qDebug() message:
OP = ?
Original poster/post
-
wrote on 2 Sept 2023, 02:11 last edited by Paul Colby 9 Feb 2023, 02:12
Hi @ademmler,
Just for inspiration, here's a class I use for capturing
std::cout
for verifying output in unit tests. You should be able to use it forstd::err
too, and then eitherqDebug()
the captured text, or invoke your installed message handler directly, as @JonB suggested.Note, though, this would only work for code that uses the
std::cout
and/orstd::cerr
C++ output streams, which is close but not quite the same as, for example, plain C code writing to thestdout
orstderr
file stream pointers, so it depends on how your included libraries, etc are writing their output./*! * Implements a simple RAII capture of output streams. */ class OutputStreamCapture { public: explicit OutputStreamCapture(std::ostream * const stream) : stream(stream) { originalBuffer = stream->rdbuf(newBuffer.rdbuf()); } std::string data() const { return newBuffer.str(); } ~OutputStreamCapture() { stream->rdbuf(originalBuffer); } private: std::ostringstream newBuffer; std::streambuf * originalBuffer; std::ostream * stream; };
Use it like:
const OutputStreamCapture capture(&std::cout); // do stuff that might output to std::cout. qDebug() << capture.data();
Again, this won't capture non-C++ streams, but at least it is portable (on Linux, macOS and Windows at least).
Hope that helps.
Cheers.
1/10