必须手动转换字符串。下面是一些(更正的)示例代码:
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "Foo.h"
#define SURROGATE_MASK 0xD800
#define is_surrogate(c) (((c) & SURROGATE_MASK) == SURROGATE_MASK)
static wchar_t calculate_code_point(wchar_t surrogate_1, wchar_t surrogate_2);
JNIEXPORT void JNICALL
Java_Foo_foo(JNIEnv *env, jobject obj, jstring bar) {
const jchar *chars = NULL;
wchar_t *result = NULL;
size_t len;
size_t source_pos, result_pos;
if (bar == NULL) {
return;
}
len = (*env)->GetStringLength(env, bar);
chars = (*env)->GetStringChars(env, bar, NULL);
if (chars == NULL) {
return;
}
result = (wchar_t *) malloc(sizeof(wchar_t) * (len + 1));
source_pos = result_pos = 0;
while (source_pos < len) {
wchar_t curr_char = chars[source_pos++];
if (is_surrogate(curr_char)) {
wchar_t surrogate_1 = curr_char;
wchar_t surrogate_2 = chars[source_pos++];
curr_char = calculate_code_point(surrogate_1, surrogate_2);
}
result[result_pos++] = curr_char;
}
result[result_pos] = L'\0';
(*env)->ReleaseStringChars(env, bar, chars);
printf("%ls\n", result);
free(result);
}
static wchar_t calculate_code_point(wchar_t high_surrogate, wchar_t low_surrogate) {
wchar_t x = (high_surrogate & ((1 << 6) - 1)) <<10 | low_surrogate & ((1 << 10) - 1);
wchar_t w = (high_surrogate >> 6) & ((1 << 5) - 1);
wchar_t u = w + 1;
return u << 16 | x;
}
请注意,此代码仅适用于使用Java 5或以上,并且您的WHARGYT数据类型为四字节长。如果您使用的是Java 1.4或以下,或者您的WHARGHETT数据类型是两个字节长,那么就不必担心代理。
这段代码还省略了一些基本的错误检查,并假定两个代理中的第一个代理项是高阶代理项(在我的机器上就是这种情况)。您可以通过它们各自的值来确定哪个代理项是高阶代理项,哪个是低阶代理项。高阶代理项介于0xd800和0xdbff之间(包括0xd800和0xdbff)。低阶代理项介于0xdc00和0xdfff之间(包括0xdc00和0xdfff)。如果发现高阶代理项未与低阶代理项配对,或者低阶代理项未与高阶代理项配对,则字符串编码不正确。