Перенаправление вывода отладочной информации в 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;
Проверили как работает перенаправление.
Добавить комментарий