J'utilise beaucoup d'instructions qDebug() <<
pour la sortie de débogage. Existe-t-il un moyen multiplateforme de rediriger cette sortie de débogage vers un fichier, sans recourir aux scripts Shell? Je suppose que open () et dup2 () fera le travail sous Linux, mais cela fonctionnera-t-il compilé avec MinGW sous Windows?
Et peut-être qu'il y a une façon Qt de le faire?
Vous devez installer un gestionnaire de messages à l'aide de la fonction qInstallMsgHandler
, puis vous pouvez utiliser QTextStream
pour écrire le débogage dans un fichier. Voici un exemple d'exemple:
#include <QtGlobal>
#include <stdio.h>
#include <stdlib.h>
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
abort();
}
}
int main(int argc, char **argv)
{
qInstallMessageHandler(myMessageOutput); // Install the handler
QApplication app(argc, argv);
...
return app.exec();
}
Tiré du doc de qInstallMsgHandler
(j'ai seulement ajouté les commentaires):
Dans l'exemple ci-dessus, la fonction myMessageOutput
utilise stderr
que vous voudrez peut-être remplacer par un autre flux de fichiers, ou réécrire complètement la fonction!
Une fois que vous avez écrit et installé cette fonction, tous vos messages qDebug
(ainsi que qWarning
, qCritical
etc) seraient redirigés vers le fichier dans lequel vous écrivez dans le gestionnaire .
De ici tous les crédits vont à esprit .
#include <QApplication>
#include <QtDebug>
#include <QFile>
#include <QTextStream>
void myMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & msg)
{
QString txt;
switch (type) {
case QtDebugMsg:
txt = QString("Debug: %1").arg(msg);
break;
case QtWarningMsg:
txt = QString("Warning: %1").arg(msg);
break;
case QtCriticalMsg:
txt = QString("Critical: %1").arg(msg);
break;
case QtFatalMsg:
txt = QString("Fatal: %1").arg(msg);
break;
}
QFile outFile("log");
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
ts << txt << endl;
}
int main( int argc, char * argv[] )
{
QApplication app( argc, argv );
qInstallMessageHandler(myMessageHandler);
...
return app.exec();
}
Voici un exemple pratique de raccordement du gestionnaire de messages par défaut.
Merci @Ross Rogers!
// -- main.cpp
// Get the default Qt message handler.
static const QtMessageHandler QT_DEFAULT_MESSAGE_HANDLER = qInstallMessageHandler(0);
void myCustomMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
// Handle the messages!
// Call the default handler.
(*QT_DEFAULT_MESSAGE_HANDLER)(type, context, msg);
}
int main(int argc, char *argv[])
{
qInstallMessageHandler(myCustomMessageHandler);
QApplication a(argc, argv);
qDebug() << "Wello Horld!";
return 0;
}
Voici une solution multiplateforme pour vous connecter à la console, si l'application a été exécutée à partir de Qt Creator et dans le fichier debug.log
, Lorsqu'elle est compilée et exécutée en tant qu'application autonome.
main.cpp :
#include <QApplication>
#include <QtGlobal>
#include <QtDebug>
#include <QTextStream>
#include <QTextCodec>
#include <QLocale>
#include <QTime>
#include <QFile>
const QString logFilePath = "debug.log";
bool logToFile = false;
void customMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QHash<QtMsgType, QString> msgLevelHash({{QtDebugMsg, "Debug"}, {QtInfoMsg, "Info"}, {QtWarningMsg, "Warning"}, {QtCriticalMsg, "Critical"}, {QtFatalMsg, "Fatal"}});
QByteArray localMsg = msg.toLocal8Bit();
QTime time = QTime::currentTime();
QString formattedTime = time.toString("hh:mm:ss.zzz");
QByteArray formattedTimeMsg = formattedTime.toLocal8Bit();
QString logLevelName = msgLevelHash[type];
QByteArray logLevelMsg = logLevelName.toLocal8Bit();
if (logToFile) {
QString txt = QString("%1 %2: %3 (%4)").arg(formattedTime, logLevelName, msg, context.file);
QFile outFile(logFilePath);
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
ts << txt << endl;
outFile.close();
} else {
fprintf(stderr, "%s %s: %s (%s:%u, %s)\n", formattedTimeMsg.constData(), logLevelMsg.constData(), localMsg.constData(), context.file, context.line, context.function);
fflush(stderr);
}
if (type == QtFatalMsg)
abort();
}
int main(int argc, char *argv[])
{
QByteArray envVar = qgetenv("QTDIR"); // check if the app is ran in Qt Creator
if (envVar.isEmpty())
logToFile = true;
qInstallMessageHandler(customMessageOutput); // custom message handler for debugging
QApplication a(argc, argv);
// ...and the rest of 'main' follows
Le formatage du journal est géré par QString("%1 %2: %3 (%4)").arg...
(pour le fichier) et fprintf(stderr, "%s %s: %s (%s:%u, %s)\n"...
(pour console).
Inspiration: https://Gist.github.com/polovik/10714049 .
Eh bien, je dirais que le moment où vous devez rediriger votre sortie de débogage vers quelque chose de différent de stderr, c'est quand vous pourriez penser à un outil de journalisation. Si vous sentez que vous en avez besoin, je vous recommande d'utiliser QxtLogger
( "La classe QxtLogger est un outil de journalisation facile à utiliser et à étendre." ) de la bibliothèque Qxt
.