如何将c++中的wchar字符串转换为更好支持的东西

How to Convert wchar wstring in C++ to something better supported?

本文关键字:更好 支持 转换 字符串 c++ 中的 wchar      更新时间:2023-10-16

我是一个Java开发人员,我遇到了编译问题与Android NDK编译c++类有wchar和wstring等。在检查了是否有任何东西可能支持这些之后,我的发现到目前为止表明没有任何东西在NDK上完全支持这些。这意味着我需要在源代码中更改它们。具体怎么做呢?由于

最好的方法是尽量用Java重写:)

但是wchar和它的好友基本上只是"以16位而不是8位字符结尾的零终止数组"。微软库只是通过并行版本的strcpy()/wstrcpy(), strlen()/wstrlen()等来进行操作。确定在哪里使用了哪些char,并实现您可能需要的几个简单函数,应该是相当简单的,不是吗?

好的,除了标记副本,我还发现了这篇有趣的文章:

TL;DR 我们选择在Android开源项目中从JNI的Android实现中提取核心宽/窄转换例程,因此转换完全在本机代码中运行

宽窄字符串转换

在移植应用程序时,由于存在多种方法和标准,这是一个相当复杂的问题。Windows Mobile (Windows CE)标准化了每个字符单位两个字节的UTF-16,除了极少数例外,ANSI或每个字符单位一个字节的原生api都被淘汰了。c#语言和。net紧凑框架也使用UTF-16。

Linux和Android原生API依赖于每个字符单位的单个字节,空终止字符串。Linux上的c++宽字符是每个字符4字节,而在Microsoft平台上是每个字符2字节。其中一个效果是将所有宽字符串的长度增加一倍,包括以L字符开头的字符串字面值。

一种可能性是将包括代理对在内的UTF-16转换为UTF-8多字节字符串,每个字符需要1到4个字节,并且可以包含嵌入的零字节。Java本机接口(JNI)提供了将Java UTF-16转换为"修改的"UTF-8的例程。修改的结果是一个不包含嵌入零的窄字符串,只有字符串末尾的零。另一个修改是将四个字节的UTF-16代理对转换为两个UTF-8字符,每个字符长三个字节,而不是一个四个字节的UTF-8字符。

使用JNI例程在宽字符串和窄字符串之间进行转换的最终结果是,宽UTF-16字符串格式与Java和Windows Mobile (CE)兼容,窄的Modified UTF-8字符串与Android/Linux OS API和C运行时库兼容。

Android C运行时库(Bionic)包含一个wchar.h来实现wcslen, wcscpy等函数,但正如头文件中的注释所指出的,Android C运行时库中没有实现实际的宽char函数。我们通过使用GNU c++编译器选项"-fshort-wchar"来解决这个问题,该选项强制编译器将宽字符视为两个字节而不是四个字节。这使得L " string "字面值每个字符两个字节,并且与UTF-16兼容。我们已经从Wine开源项目中提取了实际的宽字符运行时库。

可以使用Android中提供的JNI在本地c++宽字符串和窄字符串之间进行转换。这涉及到Java环境的往返,因此效率不高。我们选择在Android开源项目中从JNI的Android实现中提取核心宽/窄转换例程,因此转换完全在本机代码中运行