jstring(JNI) to std::string(c++) with utf8 characters

前端 未结 3 761
抹茶落季
抹茶落季 2021-02-02 11:11

How to convert jstring (JNI) to std::string (c++) with utf8 characters?

this is my code. it worked with non-utf8 characters, but i

相关标签:
3条回答
  • 2021-02-02 11:50
    jboolean isCopy;
    const char *convertedValue = (env)->GetStringUTFChars(yourJStringParam, &isCopy);
    std::string string = std::string(convertedValue, length)
    

    This works just fine. Give it a try.

    0 讨论(0)
  • 2021-02-02 11:51

    explanation is here:

    http://www.club.cc.cmu.edu/~cmccabe/blog_jni_flaws.html https://developer.android.com/training/articles/perf-jni (Region calls)

    jsize
    string_j2c(JNIEnv *env, jstring p, char *buffer) {
    
        if (buffer != NULL) {
            // Returns the length (the count of Unicode characters) of a
            // Java string.
            const jsize len = (*env).GetStringLength(p);
    
            // Translates 'len' number of Unicode characters into modified
            // UTF-8 encoding and place the result in the given buffer.
            (*env).GetStringUTFRegion(p, 0, len, buffer);
    
            // Returns JNI_TRUE when there is a pending exception;
            // otherwise, returns JNI_FALSE.
            const jboolean is_error = (*env).ExceptionCheck();
    
            if (is_error == JNI_TRUE) {
                return -1;
            }
        }
    
        // Returns the length in bytes of the modified UTF-8
        // representation of a string.
        const jsize len = (*env).GetStringUTFLength(p);
        return len;
    }
    
    const jsize len = string_j2c(env, p, NULL);
    char buffer[len];
    const jsize ret = string_j2c(env, p, buffer);
    
    if (ret == -1) { // error
    }
    else {
        __android_log_print(ANDROID_LOG_DEBUG, "Native", "%s", buffer);
    }
    
    0 讨论(0)
  • 2021-02-02 12:04

    After a lot time to find solution. i was found a way:

    In java, a unicode char will be encoded using 2 bytes (utf16). so jstring will container characters utf16. std::string in c++ is essentially a string of bytes, not characters, so if we want to pass jstring from JNI to c++, we have convert utf16 to bytes.

    in document JNI functions, we have 2 functions to get string from 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, it will return a modified utf8.

    GetStringChars will return jbyte *, we will read char code from jbytes and convert it to char in c++

    this is my solution (worked well with ascii and utf8 characters):

    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;
    }
    
    0 讨论(0)
提交回复
热议问题