C:将参数从可变参数函数传递给可变参数宏

标签 c macros variadic

我的 C 代码中内置了一个标准的日志记录 API,一个非常简单的 logF(const char *pFormat, ...)到目前为止,一直映射到 vprintf() 的东西, IE。:

void logF(const char *pFormat, ...)
{
    va_list args;
    va_start(args, pFormat);
    vprintf(pFormat, args);
    va_end(args);
}

此 API 上方的 C 代码必须在多个嵌入式平台上工作。我刚刚到达一个平台(Nordic NRF52840),在该平台上,我必须使用的底层日志接口(interface)显示为 NRF_LOG_INFO(...) 形式的可变参数宏.

问题:我如何正确通过 fn(const char *pFormat, ...)变成 BLAH(...)宏?我的脑袋疼....

这适用于 GCC 4.9.3,尽管最好有一个对 C 编译器版本相对宽松的解决方案。

编辑 1:注意到我可以重新定义我的 logF()函数成为一个可变参数宏并将其映射到那里,问题是我将拥有一个特定于平台的头文件而不是一个通用的头文件,我必须将它移到平台代码中并且每个都有一个。不是不可能,而是更困惑。

编辑 2:有人问我如何 NRF_LOG_INFO()展开。这是预处理器的相关输出:
#define NRF_LOG_INFO(...) NRF_LOG_INTERNAL_INFO( __VA_ARGS__)

#define NRF_LOG_INTERNAL_INFO(...) NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, __VA_ARGS__)

#define NRF_LOG_INTERNAL_MODULE(level,level_id,...) if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && (level <= NRF_LOG_DEFAULT_LEVEL)) { if (NRF_LOG_FILTER >= level) { LOG_INTERNAL(LOG_SEVERITY_MOD_ID(level_id), __VA_ARGS__); } }

#define LOG_INTERNAL(type,...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( __VA_ARGS__), type, __VA_ARGS__)

#define LOG_INTERNAL_X(N,...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__)

Then depending on number of args, anything up to:

#define LOG_INTERNAL_6(type,str,arg0,arg1,arg2,arg3,arg4,arg5) nrf_log_frontend_std_6(type, str, (uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4), (uint32_t)(arg5))

void nrf_log_frontend_std_6(uint32_t severity_mid,
                            char const * const p_str,
                            uint32_t val0,
                            uint32_t val1,
                            uint32_t val2,
                            uint32_t val3,
                            uint32_t val4,
                            uint32_t val5);

最佳答案

不能将参数从可变参数函数传递给可变参数宏。

由于您想从 API header 中隐藏特定于平台的宏调用,您可以使用 vsnprintf 处理函数参数。而不是 vprintf并调用格式为 "%s" 的日志记录宏以及生成的字符串缓冲区。

void logF(const char *pFormat, ...)
{
    va_list args;
    /* Choose a reasonable size or replace with dynamic allocation based on the return value of vsnprintf */
    /* This could also be a static variable or a global variable to avoid allocation of a big buffer on the stack. */
    char buffer[1024];

    va_start(args, pFormat);
    vsnprintf(buffer, sizeof(buffer), pFormat, args);

    NRF_LOG_INFO("%s", buffer);

    va_end(args);
}

请注意,您可能需要调用 NRF_LOG_FLUSH在缓冲区超出范围或被覆盖之前。见 https://devzone.nordicsemi.com/f/nordic-q-a/22647/nrf_log_info-how-to-print-log-with-string-parameter

关于C:将参数从可变参数函数传递给可变参数宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60850450/

相关文章:

rust - 如何关闭宏观卫生?

c - 将 pthread_mutex_t 传递给函数

c - 有没有办法在 C 的 printf() 函数中控制 float 的宽度和精度?

c - 使用#define 创建与 C89 std 兼容的虚拟记录

c++ - 将可变参数模板的参数分成不同的列表?

c++ - 如何找到参数包的长度?

c - c中具有不同类型参数的可变参数函数

c - 链表展平算法指针

c - 数字文字 0.e0f 是什么意思?

macros - 使用宏时每次迭代后参数递增