SPDLOG_LOGGER_CALL 和 __VA_ARGS__ 在

Posted

技术标签:

【中文标题】SPDLOG_LOGGER_CALL 和 __VA_ARGS__ 在【英文标题】:SPDLOG_LOGGER_CALL and __VA_ARGS__ in 【发布时间】:2021-08-12 18:54:27 【问题描述】:

我试图理解为什么我的可变参数在spdlog 中不起作用。我知道有一个 SPDLOG_LOGGER_INFO 宏可以做我所做的事情,但目前我需要了解 SPDLOG_LOGGER_CALL 的工作原理。所以这里是代码:

#include <iostream>
#include <spdlog/sinks/syslog_sink.h>
#include <spdlog/spdlog.h>
#include <memory>
#include <syslog.h>

int main()

    auto logger = std::make_shared<spdlog::logger>(
            "logger", 
            std::make_shared<spdlog::sinks::syslog_sink_mt>(
                "", LOG_ODELAY, LOG_USER, true));
    std::string msg = "my message";
    int i = 10;
    SPDLOG_LOGGER_CALL(logger, spdlog::level::info, "%d %s", i, msg);
    return 0;


编译后得到如下输出

Aug 12 9:38:03 mymachine test: [2021-08-12 9:38:03.424] [logger] [info] [main.cpp:30] %d %s

但是我希望在输出中看到完整的消息,即

Aug 12 9:38:03 mymachine test: [2021-08-12 9:38:03.424] [logger] [info] [main.cpp:30] 10 my message

我觉得我错过了一些小而重要的东西。有人愿意帮忙吗?

Here is where SPDLOG_LOGGER_CALL defined

【问题讨论】:

【参考方案1】:

SPDLOG_LOGGER_CALL() 只是spdlog::logger::log() 的包装器,它不使用printf 风格的格式字符串,就像您所期望的那样。如果您阅读spdlog's documentation,您会看到 spdlog 在内部使用了fmt 库:

功能丰富的格式,使用出色的fmt 库。

哪个有own syntax for format strings:

格式字符串包含用大括号 包围的“替换字段”。任何不包含在大括号中的内容都被视为文字文本,它会原封不动地复制到输出中。

这就是您在输出中看到%d %s 的原因,因为它被视为文字文本。

确实,spdlog::logger::log() ends up calling fmt::detail::vformat_to(),按原样传递您的格式字符串和参数。

所以,请尝试使用" " 而不是"%d %s"

SPDLOG_LOGGER_CALL(logger, spdlog::level::info, " ", i, msg);

或者:

SPDLOG_LOGGER_CALL(logger, spdlog::level::info, ":d :s", i, msg);

【讨论】:

以上是关于SPDLOG_LOGGER_CALL 和 __VA_ARGS__ 在的主要内容,如果未能解决你的问题,请参考以下文章

C 可变参数,“## __VA_ARGS__”宏的介绍和使用

宏定义中的###操作符和... _ _VA_ARGS_ _解析

预处理器 __VA_ARGS__ 长度的限制?

C语言 函数不定长参数 ##__VA_ARGS__经典案例

__VA_ARGS__可变参数宏

__VA_ARGS__