Qt 拾遗 004 自定义日志
QtMessageHandler
QtMessageHandler 并不是一个类,其定义如下:
typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &);
这是一个指向函数的指针,因此用户可以定义具有以下格式的自定义函数:
void myMessageHandler(QtMsgType, const QMessageLogContext&, QString&);
第一个参数 QtMsgType 是日志的等级类型:
enum QtMsgType {
QtDebugMsg,
QtWarningMsg,
QtCriticalMsg,
QtFatalMsg,
QtInfoMsg,
QtSystemMsg = QtCriticalMsg
};
我们可以将其与适当的操作关联起来:
QtMsgType 枚举值在文档中的描述第二个参数 QMessageLogContext 是写日志的当前文件名,文件行数,和当前的函数信息类。和 __FILE__、__LINE__、__FUNCTION__ 功能类似,但是我们在自定义函数中需要借助 QMessageLogContext 对象来获取是谁在做这些事。这个类主要提供如下方法:
const char * category();
const char * file();
const char * function();
int line();
int version();
第三个参数 QString 就是日志信息。
QtMessageHandler 的使用示例:
void myMessageOutput(QtMsgType type, const QMessageLogContext &context,
const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
const char *file = context.file ? context.file : "";
const char *function = context.function ? context.function : "";
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(),
file, context.line, function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(),
file, context.line, function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(),
file, context.line, function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(),
file, context.line, function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(),
file, context.line, function);
break;
}
}
qInstallMessageHandler
定义如下:
Q_CORE_EXPORT QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)
它的作用是安装之前定义的 QtMessageHandler 实例程序的函数指针。并返回指向这个消息处理程序的函数指针。
QtMessageHandler 是输出调试消息、警告、关键错误和致命错误消息的函数。Qt 库(调试模式)包含数百条警告消息,当内部错误(通常是无效的函数参数)发生时,将打印这些消息。除非 QT_NO_WARNING_OUTPUT 和/或 QT_NO_DEBUG_OUTPUT 在编译期间被设置,否则在发布模式中构建的 Qt 程序也会包含这样的警告。如果我们实现了自己的消息处理程序,则可以完全自主地控制这些消息。
默认消息处理程序将消息打印到 X11 下的标准输出或 Windows 下的调试器。如果是致命消息,应用程序将立即中止。
我们的应用每次只能定义一个消息处理程序,因为这这个设置通常是在应用程序全局左右域内进行的,目的是控制整个程序的调试信息的输出。
要恢复消息处理程序为默认,我们可以调用:
qInstallMessageHandler(0);
完整的使用实例:
#include <qapplication.h>
#include <stdio.h>
#include <stdlib.h>
void myMessageOutput(QtMsgType type, const QMessageLogContext &context,
const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
const char *file = context.file ? context.file : "";
const char *function = context.function ? context.function : "";
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(),
file, context.line, function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(),
file, context.line, function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(),
file, context.line, function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(),
file, context.line, function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(),
file, context.line, function);
break;
}
}
int main(int argc, char **argv)
{
qInstallMessageHandler(myMessageOutput);
QApplication app(argc, argv);
...
return app.exec();
}
以上