为 JNI 代码转义 Java 字符串

Escaping a Java string for JNI code

我有一个带有 Unicode 字符的 Java 字符串文字,需要将其转换为 C 字符串文字,可以使用 JNIEnv.NewString.

加载

不幸的是,上面的方法接受了一个指向unsigned short(jchar)数组的指针。我试过使用如下代码:

unsigned short str[] = {65, 66, 67};
jstring java_str = (*env)->NewString(env, str, 3);

然而,这会占用大量空间,人类不可读且难以维护。

有没有办法在 C 中将字符串文字转换为 unsigned short[],同时仍然能够使用 Java 的 UTF-16 字符?

这种转义可以通过编程方式完成吗?即,将 java.lang.String 转换为可在 C 源代码中使用的字符串文字。

你要找的不叫转义

看来您想做的是使用人类可读的字符串文字在 C 中指定一个字符串,并能够将其传递给 JNI NewString()

您将不得不继续阅读 wchar_t

What is a "wide character string" in C language? and https://en.wikibooks.org/wiki/C_Programming/C_Reference/wchar.h

你需要做的是将你的字符串文字定义为 wchar_t(使用上面帖子中解释的 "L" 符号),然后编写一个转换函数来转换这些 wchar_tjchar.

的数组

不幸的是,C 标准没有定义 wchar_t 的精确实现,而是让 C 编译器供应商按照他们的意愿去做,所以你的 C 编译器有可能不处理wchar_t 作为 16 位数量。在这种情况下,您的转换函数将无法简单地将 wchar_t 的数组转换为 jchar 的数组,而是必须将它们一个一个地转换。这有点麻烦,但可行。祝你好运!

如果您可以使用 C11 和 GCC,则可以使用新的 char16_t,它将在 GCC 中成为 UTF-16:

#include <uchar.h>

#ifndef __STDC_UTF_16__
#error "char16_t not UTF-16"
#endif

...
    char16_t my_string[] = u"abc";
    jstring java_str = (*env)->NewString(env, str, 3);

并用gcc -std=c11

编译

但无论如何,大多数时候只使用 ASCII 字符串,为此可以简单地使用

jstring java_str = (*env)->NewStringUTF(env, "abc");

这将假定字符串采用修改后的 UTF-8 编码(即 UTF-16 代理项对单独编码为 UTF-8;并且以 null 结尾)。由于 ASCII 是 UTF-8 的子集,因此这对于 ASCII 字符串非常有用。