Search code examples
javaandroidjava-native-interface

How to modify each char code of JNI String?


I have a function in my class for android.

    private String modify(String s) {
        char[] o = s.toCharArray();
        for (int i = 0; i < o.length; i++) {
            int x = o[i];
            o[i] = (char) (x - 125);
        }
        return String.valueOf(o);
    }

I want to implement similar functionality in JNI method. Means, take a JNI String, convert to char array, modifify charcode of each char in char array and return JNI string from modified char array.

Will you please guide me?


Solution

  • In jni you can get const jchar* for a jstring with GetStringChars, locally store new jchar values in array and return it as a new String. Code follows:

    C++ Version

    #include <jni.h>
    #include <string>
    #include <vector>
    
    
    extern "C" JNIEXPORT jstring JNICALL
    Java_com_example_jnitester_MainActivity_modify(
            JNIEnv* env,
            jobject /* this */,
            jstring str) {
    
        // Get jchar (2 bytes - its in unicode - not UTF) array of java string.
        // This can only be const jchar*, so you cannot modify it.
        jsize len = env->GetStringLength(str);
        jboolean isCopy;
        const jchar * strChars = env->GetStringChars(str, &isCopy);
    
        // Prepare new array of jchar, which will store new value
        std::vector<jchar> newStr;
        newStr.resize(len);
    
        // Do logic on it
        for (std::size_t i = 0; i < newStr.size(); i++) {
            int x = strChars[i];
            newStr[i] = (char) (x - 125);
        }
    
        if (isCopy == JNI_TRUE) {
            env->ReleaseStringChars(str, strChars);
        }
    
        // Return as a new java string
        return env->NewString(newStr.data(), newStr.size());
    }
    

    C only version:

    #include <jni.h>
    #include <memory.h>
    
    JNIEXPORT jstring JNICALL
    Java_com_example_jnitester_MainActivity_modify(
            JNIEnv* env,
            jobject this,
            jstring str) {
    
        // Get jchar (2 bytes - its in unicode - not UTF) array of java string.
        // This can only be const jchar*, so you cannot modify it.
        jsize len = (*env)->GetStringLength(env, str);
        jboolean isCopy;
        const jchar * strChars = (*env)->GetStringChars(env, str, &isCopy);
    
        // Prepare new array of jchar, which will store new value
        jchar* newStr = (jchar*)malloc(len * 2 + 2);
    
        // Do logic on it
        for (size_t i = 0; i < len; i++) {
            int x = strChars[i];
            newStr[i] = (char) (x - 125);
        }
    
        if (isCopy == JNI_TRUE) {
           (*env)->ReleaseStringChars(env, str, strChars);
        }
    
        // Return as a new java string
        jstring resStr = (*env)->NewString(env, newStr, len);
        free(newStr);
        return resStr;
    }