如何从JNI返回vector <vector <float >>?

时间:2019-05-30 11:50:20

标签: c++ java-native-interface

我在C ++中有一个函数:

std::vector<std::vector<float>> const &GetVertices() { return m_Vertices; }

我需要通过JNI将此值返回给Java。

因此,由于我需要返回vector中的vector,因此我认为必须使用jobjectArray,如下所示:

extern "C" JNIEXPORT jobjectArray JNICALL
Java_com_google_ar_core_examples_
java_helloar_HelloArActivity_fillListWithData(
    JNIEnv *env,
    jobject /* this */
) 

在Java中,我有以下方法:

public native Object[] fillListWithData();

所以,我的问题是,如何将vector<vector<float>>转换为jobjectArray

我知道有一种方法可以创建jobjectArray

jobjectArray verticesArr = env->NewObjectArray(verticesVec.size(), WHAT CLASS SHOULD BE HERE?,NULL);

那我该如何输入值?

完整的类实现

extern "C" JNIEXPORT jobjectArray JNICALL
Java_com_google_ar_core_examples_java_
helloar_HelloArActivity_fillListWithData(
    JNIEnv *env,
    jobject /* this */
) {
    //verticesVec
    vector<vector<float>> verticesVec = initializer->GetVertices(); // THIS VECTOR I NEED TO CONVERT TO JOBJECTARRAY
    jobjectArray verticesArr = env->NewObjectArray(verticesVec.size(), WHAT CLASS SHOULD BE HERE?,NULL);

    //HOW TO FILL THE ARRAY HERE??

    return verticesArr;
}

2 个答案:

答案 0 :(得分:0)

取决于您要如何对Java中的数据进行操作,例如添加更多元素?您没有提到这一点,所以答案无法更具体。但也许您想要float的“ java / util / ArrayList”。

以下答案应为您指明正确的方向: return a jobjectArray which contains lists of data

对于其他类型的列表,代码看起来类似。少量的网络搜索将提供几种解决方案。

如果速度(CPU /延迟)和数据量并不重要,那么我建议您将数据序列化为JSON并以字符串形式返回,而不是对Java数据结构进行所有混乱的处理。使用例如JsonCpp可以很容易地将包括对象的C ++数据类型序列化为JSON,并且在Java方面,有多个用于反序列化的包(再次是Web搜索),并且许多Java框架都为此提供了内置工具。

答案 1 :(得分:0)

您必须玩java.util.Vector。这样,您可以对...进行非常简单的映射

(C++ side) vector<vector<float> >  --->  Vector<Vector<Float>> (Java side)

代码本身将很难看。请记住,由于深奥的语法,与JNI玩起来并不是一种令人愉快的经历。

无论如何,您要做的是在C++端创建所有内容并将其传递回Java

只是摘录

  vector<vector<float> > vect {
                                 { 1.1, 1.2, 1.3 },
                                 { 2.1, 2.2, 2.3 },
                                 { 3.1, 3.2, 3.3 }
                              };
  ...
  ...

  jclass vectorClass = env->FindClass("java/util/Vector");
  ...

  jclass floatClass = env->FindClass("java/lang/Float");
  ...

  jmethodID mid = env->GetMethodID(vectorClass, "<init>", "()V");
  jmethodID addMethodID = env->GetMethodID(vectorClass, "add", "(Ljava/lang/Object;)Z");

  // Outer vector
  jobject outerVector = env->NewObject(vectorClass, mid);
  ...

  for(vector<float> i : vect) {

    // Inner vector
    jobject innerVector = env->NewObject(vectorClass, mid);

    for(float f : i) {
      jmethodID floatConstructorID = env->GetMethodID(floatClass, "<init>", "(F)V");
      ...

      // Now, we have object created by Float(f)
      jobject floatValue = env->NewObject(floatClass, floatConstructorID, f);
      ...

      env->CallBooleanMethod(innerVector, addMethodID, floatValue);
    }

    env->CallBooleanMethod(outerVector, addMethodID, innerVector);

  }

  env->DeleteLocalRef(vectorClass);
  env->DeleteLocalRef(floatClass);

您可以在此处找到完整的示例代码:

https://github.com/mkowsiak/jnicookbook/tree/master/recipeNo045

运行测试后,您可以看到基于C++的数据已传递给Java

> make test
/Library/Java/JavaVirtualMachines/jdk-12.0.1.jdk/Contents/Home/bin/java -Djava.library.path=:./lib -cp target recipeNo045.VectorOfVectors
library: :./lib
[1.1,1.2,1.3]
[2.1,2.2,2.3]
[3.1,3.2,3.3]