your programing

qDebug, qWarning, qCritical 등 출력을 리디렉션하는 방법은 무엇입니까?

lovepro 2020. 10. 14. 08:15
반응형

qDebug, qWarning, qCritical 등 출력을 리디렉션하는 방법은 무엇입니까?


qDebug() <<디버그 출력을 위해 많은 문을 사용하고 있습니다 . 셸 스크립트에 의존하지 않고 디버그 출력을 파일로 리디렉션 할 수있는 크로스 플랫폼 방법이 있습니까? 나는 open ()dup2 () 가 Linux에서 작업을 수행 할 것이라고 생각하고 있지만 Windows에서 MinGW로 컴파일되어 작동합니까?

그리고 그것을 수행하는 Qt 방법이 있습니까?


qInstallMsgHandler함수를 사용하여 메시지 처리기를 설치 한 다음을 사용 QTextStream하여 디버그 메시지를 파일 에 쓸 수 있습니다 . 다음은 샘플 예입니다.

#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();
}

의 문서에서 가져온 것입니다 qInstallMsgHandler(댓글 만 추가했습니다).

위의 예에서 함수 myMessageOutputstderr다른 파일 스트림으로 바꾸거나 함수를 완전히 다시 작성하려는 것을 사용합니다!

당신이 작성하고이 기능을 설치하면 모든 qDebug(물론 qWarning, qCritical등) 메시지는 핸들러에 파일 당신이있는 거 쓰기로 리디렉션 될 것이다.


에서 여기에 모든 신용에 간다 정신 .

#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();
}

다음은 기본 메시지 처리기를 연결하는 작업 예제입니다.

@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;
}

다음은 앱이 Qt Creator에서 실행 된 경우 앱 debug.log이 컴파일되고 독립 실행 형 앱으로 실행될 때 콘솔에 로깅하는 크로스 플랫폼 솔루션 입니다.

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

Log formatting is handled by QString("%1 %2: %3 (%4)").arg... (for the file) and fprintf(stderr, "%s %s: %s (%s:%u, %s)\n"... (for console).

Inspiration: https://gist.github.com/polovik/10714049.


Well, I would say that the moment when you need to redirect your debug output to anything different than stderr is when you could think about some logging tool. If you feel you need one I would recommend using QxtLogger ("The QxtLogger class is an easy to use, easy to extend logging tool.") from Qxt library.

참고URL : https://stackoverflow.com/questions/4954140/how-to-redirect-qdebug-qwarning-qcritical-etc-output

반응형