在Linux中加宽__FUNCTION__的版本

时间:2019-04-30 10:13:29

标签: c linux windows printf c-preprocessor

我试图编写__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 :(得分:0)

__FUNCTION__(在C99中应拼写为__func__)不是字符串文字;它实际上是一个隐式定义的字符数组。因此,您无法使用文字串联从中创建字符串文字。 (至少,不是在标准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);