0

I have a function in C++:

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

I need to return this value to Java through JNI.

So, because of the fact that I need to return vector of vector, I think that I have to use jobjectArray, like this:

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

In Java, I have this method:

public native Object[] fillListWithData();

So, my question is, how to convert vector<vector<float>> to jobjectArray?

I know that there is a method that could create jobjectArray:

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

Then how can I put in the values ?

Full class implementation

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;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Sirop4ik
  • 4,543
  • 2
  • 54
  • 121
  • Possible duplicate of [Return multidimensional array in JNI](https://stackoverflow.com/questions/43865462/) and [Return a 2D primitive array from C to Java from JNI/NDK](https://stackoverflow.com/questions/6143134/) – Remy Lebeau May 30 '19 at 15:13

2 Answers2

1

You have to play with java.util.Vector. This way, you can make a very simple mapping of

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

The code itself will be little bit ugly. Remember that playing with JNI is not quite pleasant experience (due to esoteric syntax).

Anyway, what you want to do is to create all the stuff on C++ side and pass it back to Java.

Just an excerpt

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

You can find full sample code here:

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

Once you run the test, you can see that C++ based data was passed to 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]
Oo.oO
  • 12,464
  • 3
  • 23
  • 45
0

Depends a bit on how you want to operate on the data in Java, e.g. add more elements? You didn't mention this so the answer can't be more specific. But perhaps you want "java/util/ArrayList" of float.

The following answer should point you in the right direction: return a jobjectArray which contains lists of data.

The code would look similar for other types of lists. A bit of web search will provide several solutions.

In case speed (CPU/latency) and data volume are not important, instead of all the messy handling of Java datastructures I would generally recommend serializing your data to JSON and return as string. Using e.g. JsonCpp it's easy to serialize C++ data types including objects to JSON, and on the Java side there are several packages for deserialization (web search again) and many Java frameworks come with builtin tools for this.