mbrtowc возвращает -1 для не ASCII символов на встроенном устройстве, но не на компьютере с Linux - PullRequest
0 голосов
/ 02 мая 2018

Задача

В данный момент я портирую старый код DOS для устройства на Linux на чистом C. Текст рисуется на поверхности с помощью битовых шрифтов. Я написал функцию, в которой требуется передать код Unicode, а затем нарисовать соответствующий глиф (проверено и работает с различными символами ASCII и не-ASCII). В старом исходном коде использовалась кодировка DOS, но я пытаюсь использовать UTF-8, поскольку требуется многоязыковая поддержка. Я не могу использовать SDL_ttf или аналогичные функции, так как полученные глифы недостаточно точны. Поэтому у меня есть , чтобы придерживаться битовых шрифтов.

Issue

Я написал небольшую тестовую программу на 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 в качестве ПК на встроенном устройстве. Дистрибутив Linux построен с использованием Buildroot.

1 Ответ

0 голосов
/ 04 мая 2018

Необходимо убедиться, что языковой стандарт en_US.utf8 доступен во встроенной сборке Linux. По умолчанию Buildroot ограничивает языковые стандарты, установленные в системе, двумя способами:

  • Генерируются только определенные локали, как указано в опции конфигурации BR2_GENERATE_LOCALE. По умолчанию этот список пуст, поэтому вы получаете только язык Си. Установите этот параметр конфигурации на en_US.UTF-8.
  • Все данные локали удаляются в конце сборки, кроме тех, которые указаны в BR2_ENABLE_LOCALE_WHITELIST. en_US уже находится в значении по умолчанию, поэтому, вероятно, вам не нужно его менять.

Обратите внимание, что если вы измените эти параметры конфигурации, вам нужно будет сделать полностью чистую сборку (с make clean; make), чтобы изменения вступили в силу.

...