mbrtowc在嵌入式设备上返回-1表示非ASCII字符,但在linux计算机上不返回

时间:2018-05-02 13:52:52

标签: c linux character-encoding embedded buildroot

任务

目前我正在将设备的旧DOS代码移植到纯C的Linux中。文本在bitfonts的帮助下绘制在表面上。我写了一个函数,需要传递Unicode代码点,然后绘制相应的字形(测试并使用不同的ASCII和非ASCII字符)。旧的源代码使用DOS编码,但我试图使用UTF-8,因为需要多语言支持。我不能使用SDL_ttf或类似的函数,因为生成的字形不够“精确”。因此, 坚持使用bitfonts。

问题

我编写了一个小型C测试程序,用于测试多字节字符到其相应Unicode代码点的转换(受http://en.cppreference.com/w/c/string/multibyte/mbrtowc启发)。

#include <stdio.h>
#include <locale.h>
#include <string.h>
#include <wchar.h>
#include <stdint.h>

int main(void)
{
   size_t n = 0, x = 0;
   setlocale(LC_CTYPE, "en_US.utf8");
   mbstate_t state = {0};
   char in[] = "!°水"; // or u8"zß水"
   size_t in_sz = sizeof(in) / sizeof (*in);

   printf("Processing %zu UTF-8 code units: [ ", in_sz);
   for(n = 0; n < in_sz; ++n)
   {
      printf("%#x ", (unsigned char)in[n]);
   }
   puts("]");

   wchar_t out[in_sz];
   char* p_in = in, *end = in + in_sz;
   wchar_t *p_out = out;
   int rc = 0;
   while((rc = mbrtowc(p_out, p_in, end - p_in, &state)) > 0)
   {
       p_in += rc;
       p_out += 1;
   }

   size_t out_sz = p_out - out + 1;
   printf("into %zu wchar_t units: [ ", out_sz);
   for(x = 0; x < out_sz; ++x)
   {
      printf("%u ", (unsigned short)out[x]);
   }
   puts("]");
}

输出符合预期:

Processing 7 UTF-8 code units: [ 0x21 0xc2 0xb0 0xe6 0xb0 0xb4 0 ] into 4 wchar_t units: [ 33 176 27700 0 ]

当我在嵌入式Linux设备上运行此代码时,我得到以下输出:

Processing 7 UTF-8 code units: [ 0x21 0xc2 0xb0 0xe6 0xb0 0xb4 0 ] into 2 wchar_t units: [ 33 55264 ] !字符之后,mbrtowc输出为-1,根据文档,在发生编码错误时会发生这种情况。我用不同的符号测试它,只有非ASCII字符才会出现此错误。 Linux计算机上从未发生过错误

其他信息

我在嵌入式设备上使用PFM-540I Rev. B作为pc。 Linux发行版使用Buildroot构建。

1 个答案:

答案 0 :(得分:1)

您需要确保嵌入式Linux版本中的en_US.utf8区域设置可用。默认情况下,Buildroot以两种方式限制系统上安装的语言环境:

  • 仅生成BR2_GENERATE_LOCALE配置选项指定的特定区域设置。默认情况下,此列表为空,因此您只能获得C语言环境。将此配置选项设置为en_US.UTF-8
  • 除了BR2_ENABLE_LOCALE_WHITELIST中指定的区域数据外,所有区域设置数据都会在构建结束时删除。 en_US已经是默认值,因此您可能不需要更改此内容。

请注意,如果更改这些配置选项,则需要进行完全干净的构建(使用make clean; make)才能使更改生效。