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;
}
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]