gpt4 book ai didi

c++ - QMessageLogger 魔法是如何工作的?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:34:43 26 4
gpt4 key购买 nike

我正在为 QT 应用程序开发记录器框架。出于理解和学习的目的,我没有直接使用QMessageLogger。关于一个 QMessageLogger 功能,有一件事我真的很想在我的记录器中拥有,但我不知道它是如何工作的。让我们以 qDebug 宏为例:

#define qDebug QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug

可以通过两种方式调用此函数:第一种方式:

qDebug("abc = %u", abc);

第二种方式:

qDebug() << "abc = " << abc;

我正在查看库代码,但我不太明白它是如何实现的,可以通过使用 va_args 以及一些流对象来使用 QMessageLogger。我怎样才能达到这样的效果?我非常感谢所有的帮助,非常感谢一个例子。

这是我的 print 方法主体。我需要通过“流”方式实现类似的功能:

/*!
* \brief Adds the log line to the print queue.
* \param lvl: Log level of the line.
* \param text: Formatted input for va_list.
*/
void CBcLogger::print(MLL::ELogLevel lvl, const char* text, ...)
{
// check if logger initialized
if (!m_loggerStarted)
return;

// check if log level sufficient
if (lvl > m_setLogLvl)
return;

logLine_t logline;
logline.loglvl = lvl;
logline.datetime = QDateTime::currentDateTime();

va_list argptr;
va_start(argptr, text);

char* output = NULL;
if (vasprintf(&output, text, argptr))
{
logline.logstr = output;
delete output;
}

va_end(argptr);
emit addNewLogLine(logline);
}

最佳答案

首先你要明白下面是什么

QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug

上面一行构造了一个QMessageLogger实例并立即访问其调试成员。由于它是一个宏,因此紧随其后在代码中编写的内容也很重要。

如果你看一下QMessageLogger::debug也就是说,您会看到四个重载,其中前两个与您的问题相关:

void debug(const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
QDebug debug() const;
QDebug debug(const QLoggingCategory &cat) const;
QDebug debug(CategoryFunction catFunc) const;

现在事情应该很简单了。如果您调用 qDebug("abc = %u", abc) ,你调用的是第一个重载,扩展后的宏如下:

QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug("abc = %u", abc)

或多或少等于

QMessageLogger temp(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC);
temp.debug("abc = %u", abc);

在第二种情况下,您正在调用一个返回 QDebug 的重载目的。 QDebug重载了 operator<< .扩展后的宏如下:

QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug() << "abc = " << abc;

或多或少等于

QMessageLogger temp(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC);
QDebug anotherTemp = temp.debug();
anotherTemp << "abc = " << abc;

下面是这种记录器的简单实现:

void addNewLogLine(char const* ptr){
cout << "addNewLogLine: " << ptr << endl;
}
struct LoggerHelper
{
std::stringstream s;

explicit LoggerHelper()=default;
LoggerHelper(LoggerHelper&&) = default;

~LoggerHelper(){
auto str = s.str();
addNewLogLine(str.c_str());
}

template<typename T>
LoggerHelper& operator<<(T const& val){
s << val;
return *this;
}
};

struct Logger
{
void operator()(char const* fmt, ...) const {
char* buf;
va_list args;
va_start(args, fmt);
vasprintf(&buf, fmt, args);
va_end(args);
addNewLogLine(buf);
free(buf);
}

LoggerHelper operator()() const {
return LoggerHelper{};
}
};

demo

几点说明:

  • 我坚持使用您的界面,但就个人而言,我会使用可变参数模板而不是 va_args
  • 你应该free vasprintf 返回的缓冲区. free不能与 delete 互换或 delete[]
  • 我用了std::stringstream , 但将其更改为 QTextStream或任何其他应该足够简单
  • 如果您同意 log << "foo" << "bar",则无需将 helper 作为单独的类来实现与 log() << "foo" << "bar" 相对的语法

关于c++ - QMessageLogger 魔法是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40351337/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com