Расширена версия __FUNCTION__ в Linux - PullRequest
1 голос
/ 30 апреля 2019

Я пытался написать широкую версию __FUNCTION__ для поддержки переносимого кода (Windows и Linux)

#include <stdio.h>
#include <wchar.h>
#include <errno.h>

typedef wchar_t WCHAR;
typedef const wchar_t * PCWCH;
#define WIDEN2(x)       L ## x
#define WIDEN(x)        WIDEN2(x)
#ifdef _WIN32
#define __WFUNCTION__   WIDEN(__FUNCTION__) L"(): "
#elif __linux__
#define MAX_FUNC_NAME_SIZE  1024
WCHAR func_name[MAX_FUNC_NAME_SIZE];
#define __WFUNCTION__   \
    (AsciiStrToUnicodeStr(__FUNCTION__, func_name, MAX_FUNC_NAME_SIZE) == 0) ? func_name : L"(): " 
#endif


int AsciiStrToUnicodeStr(const char *src, WCHAR *destination, unsigned int dest_max)
{
    size_t retval;
    if (!src || !destination || (dest_max == 0)) {
        return -EINVAL;
    }
    retval = mbstowcs(destination, src, dest_max);
    return (retval == -1) ? retval : 0;
}

void DbgTrace(PCWCH  pwcFormat,...)
{

    wprintf(L"%ls\n", pwcFormat);

}

void test()
{

     DbgTrace(__WFUNCTION__ L"ERROR: Null string passed\r\n");
}

int main()
{
     DbgTrace(__WFUNCTION__ L"ERROR: Null string passed\r\n");
    test();
}

Вывод содержит только имя функции, но не объединенную строку.

В чем ошибка в вышеприведенном коде.

Добавлен вывод препроцессора:

void test()
{

  DbgTrace((AsciiStrToUnicodeStr(__FUNCTION__, func_name, 1024) == 0) ? func_name : L"(): " L"ERROR: Null string passed\r\n");
}

1 Ответ

0 голосов
/ 01 мая 2019

__FUNCTION__ (что должно быть записано __func__ в C99) не является строковым литералом;это фактически неявно определенный массив символов.Таким образом, вы не можете создать строковый литерал из него с конкатенацией букв.(По крайней мере, не в стандартном C. MSVC может обрабатывать __FUNCTION__ как строковый литерал, но он не переносим.)

Конкатенация строковых литералов выполняется сразу после предварительной обработки и может применяться только к строковым литералам., а не переменные.func_name " extra text" будет синтаксической ошибкой.

Но, как видите, это не то, что создает расширение макроса.Конкатенируемыми литералами являются L"(): " and L «ошибка: передана строка NULL».

Обратите внимание, что если бы __func__ был строковым литералом, вы могли бы превратить его в широкий строковый литерал с конкатенацией строк.Например:

L"" __FILE__ ": the file"

является допустимым широким строковым литералом.(Но он не будет работать в Windows. См. https://stackoverflow.com/a/21789691/1566221).

Поскольку __func__ не является строковым литералом, его невозможно расширить в препроцессоре. (Ни преобразовать его в широкую строку). Лучше всего использовать его самостоятельно при вызове printf (или wprintf):

 printf("%s %s, funcname, message);
...