Как я могу использовать vsprintf / vsnprintf в макросе? - PullRequest
1 голос
/ 25 июня 2011

Я пытаюсь написать макрос, чтобы упростить использование LOG4CPLUS. Но у меня возникли проблемы при написании макроса.

Это что-то в моем файле cpp:

Logger logger = Logger::getInstance("ManagerServer");

После этого я могу записать одну строку следующим образом:

LOG4CPLUS_ERROR(logger, logEvent);

Я просто хочу написать макрос, затем я могу изменить logEvent на некоторый переменный аргумент. И используйте как это:

LogErr("failed");
LogErr("failed times %d", iTimes);

Итак, я пишу так:

#define LogErr(fmt, args...)\
    do {\
        char szBuf[MAX_LOG_BUFFER_SIZE];\
        memset(szBuf, 0, MAX_LOG_BUFFER_SIZE);  \
        vsnprintf(szBuf, MAX_LOG_BUFFER_SIZE, fmt, ##args); \
        LOG4CPLUS_ERROR(logger, szBuf);\
    } while(0)

Но когда я компилирую. g ++ дай мне это сообщение:

ошибка: ожидаемое первичное выражение до маркера ')'

Кто-нибудь может мне помочь? Я действительно ценю это.

Ответы [ 4 ]

2 голосов
/ 25 июня 2011

Упс ... тег C был удален

Проблема заключается в расширении макроса, когда задано недостаточно параметров (LogErr("failed")). Это не работает в C.

Попробуйте добавить фиктивный параметр

LogErr("failed", 0);
/* or better */
LogErr("%s", "failed");

Также вы не можете использовать функции v* внутри макроса, как вы пытаетесь: препроцессор не знает о переменных аргументах и ​​не может создавать объекты типа va_list.


В C99 один из способов сделать то, что вы пытаетесь сделать, это

#include <stdio.h>
#include <string.h>

#define MAX_LOG_BUFFER_SIZE 100

#define LogErr(fmt, ...)                                      \
  do {                                                        \
    char szBuf[MAX_LOG_BUFFER_SIZE];                          \
    memset(szBuf, 0, MAX_LOG_BUFFER_SIZE);                    \
    snprintf(szBuf, MAX_LOG_BUFFER_SIZE, fmt, ##__VA_ARGS__); \
    /* LOG4CPLUS_ERROR(logger, szBuf); */                     \
  } while(0)

int main(void) {
  LogErr("err %d", 4);
  /*LogErr("failed");*/
  LogErr("%s", "failed");
  return 0;
}

Примечание: snprintf и ##__VA_ARGS

1 голос
/ 25 июня 2011

Спасибо pmg, Ферруччо и всем вам.Вы, ребята, действительно спасли меня!

Этот код отлично работает на моем компьютере.Кажется, я пропустил vsnprintf и snprintf.

#define Log(fmt, args...) \
    do {\
        char szBuf[MAX_LOG_BUFFER_SIZE];\
        snprintf(szBuf, MAX_LOG_BUFFER_SIZE-1, fmt, ##args);\
        LOG4CPLUS_ERROR(logger, szBuf);\
    } while(0)

int main() {
    Log("Hello macro.");
    Log("Hello macro %d", 1);
    Log("Hello macro %s, %d", "foo", 2);

    return 0;
}

Еще раз спасибо!

1 голос
/ 25 июня 2011

Вам не хватает запятой после параметра args.

#define LogErr(fmt, args, ...)\
                        ^

Кроме того, я не знаю, поддерживает ли g ++ в настоящее время переменные макросы, это функция C ++ 11. (Хотя я верю, что их поддерживает компилятор C).

0 голосов
/ 20 сентября 2012

Последние (1.1.0+) версии Log4cplus поддерживают ведение журналов с использованием макросов в стиле printf.Ваш пример в OP будет выглядеть так:

LOG4CPLUS_ERROR_FMT(logger, "failed");
LOG4CPLUS_ERROR_FMT(logger, "failed times %d", iTimes);

См. loggingmacros.h для деталей реализации, если вы все еще хотите переопределить его по-другому.

...