我如何从 JNI return vector<vector<float>>?
How can I return vector<vector<float>> from JNI?
我有一个 C++ 函数:
std::vector<std::vector<float>> const &GetVertices() { return m_Vertices; }
我需要通过 JNI return 这个值到 Java。
所以,因为我需要 return vector
of 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);
那我怎么输入值呢?
完全class实施
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;
}
取决于您希望如何对 Java 中的数据进行操作,例如添加更多元素?您没有提到这一点,所以答案不能更具体。但也许你想要 "java/util/ArrayList" 的浮动。
以下答案应该能为您指明正确的方向:
return a jobjectArray which contains lists of data.
对于其他类型的列表,该代码看起来类似。进行一些网络搜索将提供多种解决方案。
如果速度 (CPU/latency) 和数据量不重要,而不是对 Java 数据结构的所有混乱处理,我通常建议将数据序列化为 JSON 和 return 作为字符串。使用例如JsonCpp 很容易将包含对象的 C++ 数据类型序列化为 JSON,并且在 Java 方面有几个用于反序列化的包(再次网络搜索)和许多 Java 框架来了内置工具。
你必须和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/recipes/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]
我有一个 C++ 函数:
std::vector<std::vector<float>> const &GetVertices() { return m_Vertices; }
我需要通过 JNI return 这个值到 Java。
所以,因为我需要 return vector
of 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);
那我怎么输入值呢?
完全class实施
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;
}
取决于您希望如何对 Java 中的数据进行操作,例如添加更多元素?您没有提到这一点,所以答案不能更具体。但也许你想要 "java/util/ArrayList" 的浮动。
以下答案应该能为您指明正确的方向: return a jobjectArray which contains lists of data.
对于其他类型的列表,该代码看起来类似。进行一些网络搜索将提供多种解决方案。
如果速度 (CPU/latency) 和数据量不重要,而不是对 Java 数据结构的所有混乱处理,我通常建议将数据序列化为 JSON 和 return 作为字符串。使用例如JsonCpp 很容易将包含对象的 C++ 数据类型序列化为 JSON,并且在 Java 方面有几个用于反序列化的包(再次网络搜索)和许多 Java 框架来了内置工具。
你必须和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/recipes/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]