android - 带有 utf8 字符的 jstring(JNI) 到 std::string(c++)

标签 android c++ c++11 java-native-interface share

如何将 jstring (JNI) 转换为 std::string (c++) 与 utf8 字符?

这是我的代码。它适用于非 utf8 字符,但适用于 utf8 字符。

std::string jstring2string(JNIEnv *env, jstring jStr){
    const char *cstr = env->GetStringUTFChars(jStr, NULL);
    std::string str = std::string(cstr);
    env->ReleaseStringUTFChars(jStr, str);
    return str;
}

最佳答案

经过很长时间才找到解决方案。我找到了一条路:

在 java 中,unicode char 将使用 2 个字节 (utf16) 进行编码。所以 jstring 将包含字符 utf16。 c++ 中的 std::string 本质上是一个字节串,而不是字符,所以如果我们想将 jstringJNI 传递到 c++,我们已经将 utf16 转换为字节。

在文档 JNI functions 中,我们有 2 个函数从 jstring 中获取字符串:

// Returns a pointer to the array of Unicode characters of the string. 
// This pointer is valid until ReleaseStringchars() is called.
const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy);


// Returns a pointer to an array of bytes representing the string 
// in modified UTF-8 encoding. This array is valid until it is released 
// by ReleaseStringUTFChars().
const char * GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy);

GetStringUTFChars,它会返回一个 modified utf8 .

GetStringChars 将返回 jbyte *,我们将从 jbytes 中读取 char 代码并在 c++ 中将其转换为 char

这是我的解决方案(适用于 asciiutf8 字符):

std::string jstring2string(JNIEnv *env, jstring jStr) {
    if (!jStr)
        return "";

    const jclass stringClass = env->GetObjectClass(jStr);
    const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
    const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(jStr, getBytes, env->NewStringUTF("UTF-8"));

    size_t length = (size_t) env->GetArrayLength(stringJbytes);
    jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);

    std::string ret = std::string((char *)pBytes, length);
    env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);

    env->DeleteLocalRef(stringJbytes);
    env->DeleteLocalRef(stringClass);
    return ret;
}

关于android - 带有 utf8 字符的 jstring(JNI) 到 std::string(c++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41820039/

相关文章:

java - 如何同时完成Firebase Storage Task和Firestore Task?

android - 如何在单个通知的状态栏中显示单个通知图标

java - 将 Delphi 5 引擎控制应用程序转换为 Android - 需要有关方法的建议

c++ - 释放 vector 的 wchar_t*

c++ - 如果可能,取消对 C++ 类型指针的引用

android - 在 Android 的 ListView 中添加页眉

c++ - 我们可以使用 FireBase 云消息传递在 Windows 桌面/控制台或 Linux 控制台应用程序上使用 C++ 发送或接收消息或两种方式吗?

c++ - 重载子类

c++ - 可变继承

c++ - 隐式默认可构造的含义?