1. ホーム
  2. android

[解決済み] jstring(JNI) から std::string(c++) へ utf8 文字で変換する。

2022-02-28 23:32:46

質問

変換方法 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では、ユニコード文字が2バイトでエンコードされます( utf16 となります。 jstring はコンテナ文字 utf16 . std::string は基本的に文字ではなくバイト列なので、もし jstring から JNI から c++ に変換しています。 utf16 をバイトに変換します。

文書中 JNI関数 jstringから文字列を取得するための関数が2つあります。

// 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 を返します。 修正されたutf8 .

GetStringChars は jbyte * を返すので、jbyte から 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;
}