I think I have an idea of what to do, I just wanted to poke the SO community to see if I'm on the right track as I haven't seen any information about this specific topic from my research.
I have some custom Java (data model) classes that I want to be accessible on my native C++ side of my application. I realize that these two environments are fairly separate, so I'll have to most likely create a "copy" of my data models in c++, and initialize them in my nativeLib JNI file?
I'm assuming I can't just "convert" the java class to the c++ class, since the compiler probably won't be able to do such a conversion. I'll have to manage each of the fields that I need manually through a JNI method call.
Is this correct, or is there a better way that I'm not aware of?
I suppose an example might look like this:
Foo.java
public class Foo {
boolean A;
boolean B;
boolean C;
}
native-lib.cpp
extern "C" {
std::unique_ptr<Foo> foo;
JNIEXPORT void JNICALL
Java_com_example_user_project_native_1Foo(JNIEnv *env, jobject instance, jbool jbooleanA, jbool jbooleanB, jbool jbooleanC) {
Foo->setA(jbooleanA);
Foo->setB(jbooleanB);
Foo->setC(jbooleanC);
}
Foo.h
class Foo {
private:
bool A;
bool B;
bool C;
public:
// add setters & getters here, or any other needed functions
}
While finding the solution to my question, I found out more specifics to why the conversion doesn't work:
ArrayList (from Java) is not perceived as a jobjectArray in the JNI framework. It is recognized as a jObject. So if you wanted to convert an ArrayList object you would have to create a new jobjectArray in JNI
You cannot access methods from the ArrayList class (like get, or set), as the class of the parameters is a generic. Generics aren't allowed in JNI
Because of these two reasons, an ArrayList object cannot be converted and sent through JNI. Instead I chose to convert my ArrayList into an object array myClass[]
on the Java side, then send that through.
Bellow is the code I wrote for this conversion:
javaClass.java
void setFooArray(ArrayList<Foo> param) {
Foo[] fooArray = new Foo[param.size()];
for (int i = 0; i < param.size(); i++) {
fooArray[i] = param.get(i);
}
native_setFooArray(fooArray, fooArray.length);
}
// ...
private native void native_setFooArray(Foo[] fooArray, int size);
native-lib.cpp
JNIEXPORT void JNICALL
java_com_example_my_project_native_1setFooArray(JNIEnv *env, jobject instance, jobjectArray fooArray, jint arraySize) {
std::vector<Foocpp> cfooArray;
jfieldID fidA;
jfieldID fidB;
for (jint i = 0; i < arraySize; i++) {
jobject jfoo = env->GetObjectArrayElement(fooArray, i);
jclass cfoo = env->GetObjectClass(jfoo);
fidA = env->getFieldID(cfoo, "A", "I");
fidB = env->GetFieldID(cfoo, "B", "I");
jint A = env->GetIntField(cfoo, fidA);
jint B = env->GetIntField(cfoo, fidB);
const Foocpp foo = Foocpp(A, B);
cfooArray.push_back(foo);
}
class->setFooArray(cfooArray);
Useful links: