我有一个 Java 应用程序,它通过 JNI 使用 C++ DLL。 DLL 的一些方法采用字符串参数,其中一些方法返回也包含字符串的对象。
目前DLL不支持Unicode,所以字符串处理比较简单:
- Java 调用 String.getBytes() 并将生成的数组传递给 DLL,DLL 将数据简单地视为 char*。
- DLL 使用 NewStringUTF() 从 const char* 创建 jstring。
我现在正在修改 DLL 以支持 Unicode,切换到使用 TCHAR 类型(当定义 UNICODE 时使用 Windows 的 WCHAR 数据类型)。修改 DLL 进行得很顺利,但我不确定如何修改代码的 JNI 部分。
我现在唯一能想到的是:
- Java 调用 String.getBytes(String charsetName) 并将生成的数组传递给 DLL,DLL 将数据视为 wchar_t*。
- DLL 不再创建字符串,而是将原始字符串数据传递给 jbyteArrays。 Java 使用 String(byte[] bytes, String charsetName) 构造函数来实际创建 String。
此方法的唯一问题是我不确定要使用什么字符集名称。 WCHAR 的长度为 2 个字节,所以我很确定它是 UTF-16,但在 Java 端有 3 种可能性。 UTF-16、UTF-16BE 和 UTF-16LE。我还没有找到任何文档来告诉我字节顺序是什么,但我可能可以通过一些快速测试来弄清楚。
有没有更好的方法?如果可能的话,我想继续在 DLL 中构建 jstring 对象,因为这样我就不必修改这些方法的任何用法。但是,NewString JNI 方法不采用字符集标识符。
最佳答案
This answer建议不能保证 WCHARS 的字节顺序......
因为你在 Windows 上,你可以尝试 <a href="http://msdn.microsoft.com/en-us/library/aa450989.aspx" rel="noreferrer noopener nofollow">WideCharToMultiByte</a>
将 WCHAR 转换为 UTF-8,然后使用您现有的 JNI 代码。
您需要小心使用 WideCharToMultiByte由于缓冲区溢出的可能性 lpMultiByteStr
范围。要解决这个问题,您应该调用该函数两次,首先是 lpMultiByteStr
设置为 NULL
和 cbMultiByte
设置为零 - 这将返回所需 lpMultiByteStr
的长度缓冲而不试图写入它。获得长度后,您可以分配所需大小的缓冲区并再次调用该函数。
示例代码:
int utf8_length;
wchar_t* utf16 = ...;
utf8_length = WideCharToMultiByte(
CP_UTF8, // Convert to UTF-8
0, // No special character conversions required
// (UTF-16 and UTF-8 support the same characters)
utf16, // UTF-16 string to convert
-1, // utf16 is NULL terminated (if not, use length)
NULL, // Determining correct output buffer size
0, // Determining correct output buffer size
NULL, // Must be NULL for CP_UTF8
NULL); // Must be NULL for CP_UTF8
if (utf8_length == 0) {
// Error - call GetLastError for details
}
char* utf8 = ...; // Allocate space for UTF-8 string
utf8_length = WideCharToMultiByte(
CP_UTF8, // Convert to UTF-8
0, // No special character conversions required
// (UTF-16 and UTF-8 support the same characters)
utf16, // UTF-16 string to convert
-1, // utf16 is NULL terminated (if not, use length)
utf8, // UTF-8 output buffer
utf8_length, // UTF-8 output buffer size
NULL, // Must be NULL for CP_UTF8
NULL); // Must be NULL for CP_UTF8
if (utf8_length == 0) {
// Error - call GetLastError for details
}
关于java - 通过 JNI 将双字节 (WCHAR) 字符串从 C++ 传递到 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/870414/