Широкие и узкие преобразования строк символов
Это довольно сложная проблема при переносе приложения из-за множества методов и стандартовв существовании.Windows Mobile (Windows CE), стандартизированная для двухбайтовых блоков символов UTF-16, и, за редким исключением, собственные API ANSI или один байт на символьные блоки были исключены.Язык C # и .NET Compact Framework также используют UTF-16.
Нативный API Linux и Android используют одиночный байт на символьную единицу, строки с нулевым символом в конце.Широкий символ C ++ в Linux составляет 4 байта на символ, в отличие от 2 байтов на символьную единицу на платформе Microsoft.Одним из эффектов является удвоение длины всех строк широких символов, включая строковые литералы, перед которыми стоит символ L.
Одна возможность - преобразовать UTF-16, включая суррогатные пары, в многобайтовые строки UTF-8, для которых может потребоваться однадо четырех байтов для каждого символа, и может содержать встроенные нулевые байты.Собственный интерфейс Java (JNI) предоставляет процедуры для перевода Java UTF-16 в «модифицированный» UTF-8.Изменения приводят к узкой символьной строке, не содержащей встроенных нулей, только ноль в конце строки.Другая модификация заключается в преобразовании четырехбайтовой суррогатной пары UTF-16 в два символа UTF-8, каждый длиной три байта вместо одного символа UTF-8, длиной четыре байта.
Конечный результат использования подпрограмм JNIперевод между широкими и узкими строками заключается в том, что широкий формат строки UTF-16 совместим как с Java, так и с Windows Mobile (CE), а узкая измененная строка UTF-8 совместима с API Android / Linux OS и библиотекой времени выполнения C.
Библиотека времени выполнения Android C (Bionic) содержит файл wchar.h для реализации таких функций, как wcslen, wcscpy и т. Д., Но, как отмечено в комментариях в заголовке, никакие фактические функции широких символов не реализуются вAndroid C библиотека времени выполнения.Мы решаем это, используя опцию компилятора GNU C ++ «-fshort-wchar», которая заставляет компилятор обрабатывать широкие символы как два байта вместо четырех байтов.Это делает L «строку» буквальным двумя байтами на символ и совместимым с UTF-16.Мы извлекли фактическую библиотеку времени выполнения широких символов из проекта с открытым исходным кодом Wine.
Можно использовать JNI, поставляемый в Android, для перевода между родными широкими C ++ и узкими строками.Это включает в себя круговое путешествие по среде Java и, следовательно, не очень эффективно. Мы решили извлечь базовые процедуры широкого / узкого преобразования из реализации JNI для Android в проекте с открытым исходным кодом Android, чтобы преобразование полностью выполнялось в собственном коде .