JNI - java ArrayList conversion to c++ std::string*

*爱你&永不变心* 提交于 2019-12-21 17:33:19

问题


I am trying to make a data conversion with JNI in c++. I have come into trouble working with java's ArrayList of strings, since I have not been able to convert such a data into a c++ vector or std::string*.

I would like to know how this conversion can be made without sacrificing too much performance, if possible. Any ideas would be appreciated.


回答1:


I don't know if this fits your performance requirements, but it may be a good start.

For both options assume that jobject jList; is your ArrayList.

Option 1

Convert the List into an array and iterate on the array (maybe more applicable if you have a LinkedList instead of an ArrayList)

// retrieve the java.util.List interface class
jclass cList = env->FindClass("java/util/List");

// retrieve the toArray method and invoke it
jmethodID mToArray = env->GetMethodID(cList, "toArray", "()[Ljava/lang/Object;");
if(mToArray == NULL)
    return -1;
jobjectArray array = (jobjectArray)env->CallObjectMethod(jList, mToArray);

// now create the string array
std::string* sArray = new std::string[env->GetArrayLength(array)];
for(int i=0;i<env->GetArrayLength(array);i++) {
    // retrieve the chars of the entry strings and assign them to the array!
    jstring strObj = (jstring)env->GetObjectArrayElement(array, i);
    const char * chr = env->GetStringUTFChars(strObj, NULL);
    sArray[i].append(chr);
    env->ReleaseStringUTFChars(strObj, chr);
}

// just print the array to std::cout
for(int i=0;i<env->GetArrayLength(array);i++) {
    std::cout << sArray[i] << std::endl;
}

Option 2

An alternative would be to use the List.size() and List.get(int) methods to retrieve the data from the list. As you use an ArrayList this solution would also be okay as the ArrayList is an RandomAccessList.

// retrieve the java.util.List interface class
jclass cList = env->FindClass("java/util/List");

// retrieve the size and the get method
jmethodID mSize = env->GetMethodID(cList, "size", "()I");
jmethodID mGet = env->GetMethodID(cList, "get", "(I)Ljava/lang/Object;");

if(mSize == NULL || mGet == NULL)
    return -1;

// get the size of the list
jint size = env->CallIntMethod(jList, mSize);
std::vector<std::string> sVector;

// walk through and fill the vector
for(jint i=0;i<size;i++) {
    jstring strObj = (jstring)env->CallObjectMethod(jList, mGet, i);
    const char * chr = env->GetStringUTFChars(strObj, NULL);
    sVector.push_back(chr);
    env->ReleaseStringUTFChars(strObj, chr);
}

// print the vector
for(int i=0;i<sVector.size();i++) {
    std::cout << sVector[i] << std::endl;
}

_edited: replaced JNI_FALSE with NULL_
_edited: replaced insert with push_back_




回答2:


You could also use classic java iterators from within JNI, having the loop equally optimized both for ArrayList and LinkedList.

jobject jIterator = env->CallObjectMethod(jList, env->GetMethodID(env->GetObjectClass(jList), "iterator", "()Ljava/util/Iterator;"));
jmethodID nextMid = env->GetMethodID(env->GetObjectClass(jIterator), "next", "()Ljava/lang/Object;");
jmethodID hasNextMid = env->GetMethodID(env->GetObjectClass(jIterator), "hasNext", "()Z");

while (env->CallBooleanMethod(jIterator, hasNextMid)) {
    jobject jItem = env->CallObjectMethod(jIterator, nextMid);
    /* do something with jItem */
}


来源:https://stackoverflow.com/questions/24403340/jni-java-arraylist-conversion-to-c-stdstring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!