将字符串的arraylist从Native java返回到JNI

SAC*_*ACH 8 java java-native-interface native arraylist

           ArrayList<String> myArraylist;          

           public ArrayList<String> getData(){
               myArraylist = new ArrayList<String>();          
               myArraylist.add("1267982563");
               myArraylist.add("2345678");
               myArraylist.add("5432789");
               return myArraylist;
           }
Run Code Online (Sandbox Code Playgroud)

如何从JNI端的上述方法获取每个项目,并推送到向量并从JNI返回到JNI层中的其他CPP调用.

Ale*_*ohn 16

将ArrayList转换为std :: vector <std :: string>:

static jclass java_util_ArrayList;
static jmethodID java_util_ArrayList_;
jmethodID java_util_ArrayList_size;
jmethodID java_util_ArrayList_get;
jmethodID java_util_ArrayList_add;
static thread_local JNIEnv* env;

void init() {
  java_util_ArrayList      = static_cast<jclass>(env->NewGlobalRef(env->FindClass("java/util/ArrayList")));
  java_util_ArrayList_     = env->GetMethodID(java_util_ArrayList, "<init>", "(I)V");
  java_util_ArrayList_size = env->GetMethodID (java_util_ArrayList, "size", "()I");
  java_util_ArrayList_get  = env->GetMethodID(java_util_ArrayList, "get", "(I)Ljava/lang/Object;");
  java_util_ArrayList_add  = env->GetMethodID(java_util_ArrayList, "add", "(Ljava/lang/Object;)Z");
}

std::vector<std::string> java2cpp(jobject arrayList) {
  jint len = env->CallIntMethod(arrayList, java_util_ArrayList_size);
  std::vector<std::string> result;
  result.reserve(len);
  for (jint i=0; i<len; i++) {
    jstring element = static_cast<jstring>(env->CallObjectMethod(arrayList, java_util_ArrayList_get, i));
    const char* pchars = env->GetStringUTFChars(element, nullptr);
    result.emplace_back(pchars);
    env->ReleaseStringUTFChars(element, pchars);
    env->DeleteLocalRef(element);
  }
}
Run Code Online (Sandbox Code Playgroud)

将ArrayList从JNI推送回Java

如果你不在JNI中修改这个列表,那么最好的策略就是在你的本机代码中的某个地方保持对它的全局引用.如果稍微修改它,请保持此jobject始终是最新的(您可能需要方法java_util_ArrayList_addjava_util_ArrayList_set).

如果您选择从头开始重建矢量列表,您将展开上述方法:

jobject cpp2java(std::vector<std::string> vector) {
  jobject result = env->NewObject(java_util_ArrayList, java_util_ArrayList_, vector.size());
  for (std::string s: vector) {
    jstring element = env->NewStringUTF(s.c_str());
    env->CallBooleanMethod(result, java_util_ArrayList_add, element);
    env->DeleteLocalRef(element);
  }
  return result;
}
Run Code Online (Sandbox Code Playgroud)

无论如何,在使用Jni时要小心线程,在本机线程被销毁之前始终附加本机线程并分离.

  • @Pixel我相信在这种情况下,`static_cast`更好地表达了程序员的意图。所有 C++ 支持都是事后添加到 JNI 中的,集成从来都不是干净的。我知道的最好方法是禁用 JNI *'classes'* `static_cast` 上下文中弹出的每一行的特定警告。 (2认同)
  • @Raii 我不明白你的问题。方法 ID 是与线程无关的常量。“JNIEnv *”是针对每个线程的。`java_util_ArrayList` 是一个 Java 对象。如果获得全局引用,则可以跨线程和 JNI 调用使用它,但“FindClass”函数返回本地引用,因此我调用“NewGlobalRef”。 (2认同)