Вторник, 19.08.2025 19:00

Перенаправление вывода отладочной информации в Qt6

Перенаправление вывода отладочной информации в Qt6

Фреймворк Qt6 предоставляет широкие возможности управления выводом отладочной информации. Один из них – перенаправление вывода функций отладки, самая часто использующаяся из них qDebug().

Сегодня мы рассмотрим перенаправление вывода отладочной информации в канал вывода stderr.

Мы будем использовать код и статьи - https://blog.altuninvv.ru/qt/qt6/отладка-проектов-qt-quick-qml-в-vscode.

Создаем класс для перенаправления вывода в stderr

Добавим новый класс DebugRedirector

Заголовок:

#ifndef DEBUGREDIRECTOR_H
#define DEBUGREDIRECTOR_H

#include <QQmlApplicationEngine>
#include <QDebug>

#include <iostream>



class DebugRedirector
{
public:
    DebugRedirector();
    ~DebugRedirector();
    
    static void stdErrorHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
    static void __errorHandler(FILE *output, QtMsgType type, const QMessageLogContext &context, const QString &msg);
};

#endif

Реализация:

#include "debugredirector.h"

DebugRedirector::DebugRedirector()
{
}

DebugRedirector::~DebugRedirector()
{
}

void DebugRedirector::stdErrorHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg)
{
    DebugRedirector::__errorHandler(stderr, type, context, msg);
}

void DebugRedirector::__errorHandler(FILE * output, QtMsgType type, const QMessageLogContext & context, const QString & msg)
{
    QByteArray localMsg = msg.toLocal8Bit();
    switch (type)
    {
    case QtDebugMsg:
        fprintf(output, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtInfoMsg:
        fprintf(output, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtWarningMsg:
        fprintf(output, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtCriticalMsg:
        fprintf(output, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
        break;
    case QtFatalMsg:
        fprintf(output, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
        fflush(stdout);
        fflush(stderr);
        abort();
    }

    fflush(stdout);
    fflush(stderr);

}

Класс объявляет статический метод stdErrorHandler, который получает от движка Qt6 данные отправляемые функциями QDebug и выводит информацию в более подробном виде, добавляя имя файла и номер строки. При этом вывод происходит в канал вывода stderr. Так как в VSCode панель DEBUG CONSOLE умеет перехватывать вывод в этот канал, то и при отладке в режиме QML мы получаем все сообщения.

Далее вы можете модернизировать данный класс как вам будет удобнее, например выводить qInfo() в stdout, а всё остальное в stderr или изменить формат вывода.

Настройка перенаправления вывода в проекте Qt6

Чтобы использовать данный класс в нашем проекте нам нужно включить файлы в CMakeLists.txt.

Откроем файл CMakeLists.txt и добавим строки:

    debugredirector.cpp
    debugredirector.h

в блок:

qt_add_executable

У нас получится:

qt_add_executable(appqttest1
    main.cpp
    debugredirector.cpp
    debugredirector.h
)

Сохраним файл. Будет запущена реконфигурация проекта.

В файл main.cpp добавим:

#include "debugredirector.h"

После:

QGuiApplication app(argc, argv);

Добавим:

qInstallMessageHandler(DebugRedirector::stdErrorHandler);

Данная строка регистрирует статический метод класса в качестве обработчика сообщений Qt6.

Добавим новую отладочную информацию, для этого удалим лишний код между:

engine.load(url);
...
return app.exec();

И добавим:

    qDebug() << "Started!";

    std::cout << "Output with cout <<\n";

    printf("Output with printf()\n");

У нас получится:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include <iostream>

#include "debugredirector.h"

int main(int argc, char *argv[])
{

    QGuiApplication app(argc, argv);

    qInstallMessageHandler(DebugRedirector::stdErrorHandler);

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/qttest1/Main.qml"));
    QObject::connect(
        &engine,
        &QQmlApplicationEngine::objectCreationFailed,
        &app,
        []()
        { QCoreApplication::exit(-1); },
        Qt::QueuedConnection);
    engine.load(url);

    qDebug() << "Started!";

    std::cout << "Output with cout <<\n";

    printf("Output with printf()\n");

    return app.exec();
}

Произведем обычный запуск. Понажимаем на кнопки.

Во вкладке Terminal получим:

PS C:\Users\user\Documents\qttest1\build> ."C:/Users/user/Documents/qttest1/build/appqttest1.exe"
QML debugging is enabled. Only use this in a safe environment.
Debug: Started! (C:\Users\user\Documents\qttest1\main.cpp:28, int main(int, char**))
Output with cout <<
Output with printf()
Debug: Setup (qrc:/qttest1/Main.qml:33, expression for onClicked)
Debug: Clicked c= 13 (qrc:/qttest1/Main.qml:48, expression for onClicked)

Запустим проект в режиме отладки QML Debug. Все сообщения отображаются в консоли DEBUG CONSOLE!

Заключение

Сегодня мы рассмотрели перенаправление вывода отладочной информации в канал вывода stderr:

Создали класс DebugRedirector со статическим методом stdErrorHandler для перенаправления вывода в stderr;

Добавили новый класс к нашему проекту;

Перенаправили вывод, зарегистрировав обработчик с помощью функции qInstallMessageHandler;

Проверили как работает перенаправление.

Категория Qt6
Теги Qt Qt6 Cpp CMAKE

Добавить комментарий

Простой текст

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Строки и абзацы переносятся автоматически.
  • Адреса веб-страниц и email-адреса преобразовываются в ссылки автоматически.
Просмотров: 216