簡體   English   中英

jstring(JNI) 到 std::string(c++) 與 utf8 字符

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

如何使用utf8字符將jstring (JNI) 轉換為std::string (c++)?

這是我的代碼。 它適用於非 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 函數中,我們有 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 ,它將返回修改后的 utf8

GetStringChars將返回 jbyte *,我們將從 jbytes 中讀取字符代碼並將其轉換為 C++ 中的字符

這是我的解決方案(適用於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;
}
jboolean isCopy;
const char *convertedValue = (env)->GetStringUTFChars(yourJStringParam, &isCopy);
std::string string = std::string(convertedValue, length)

這工作得很好。 試一試。

解釋在這里:

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

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);
}

我調整了@Nikhil Tambe的答案,看起來像這樣:

jboolean isCopy;
const char *convertedValue = (env)->GetStringUTFChars(yourJStringParam, &isCopy);
std::string str = convertedValue;

那奏效了! 因為在標准 C++ 中,字符串文字的類型是const char * ,因此您可以將const char *convertedValue分配給std::string類型的變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM