如何在Android NDK上使用JNI在C和Java之间传递复杂结构

我在Android应用程序的C代码中有一个复杂的结构,我想在Java端使用它。 我已经用google和stackoverflow做了一些研究,所以我从我的C结构创建了java类,但现在如何用Java创建它。

我已经找到了这些信息,关于在类中创建指针并在C端使用它:

Get the field ID : (*env)->GetFieldID(...) Get the pointer : (*env)->GetLongField(...) Set the pointer : (*env)->SetLongField(...) 

但我不明白它是如何运作的……

在上面,你可以找到我到目前为止所做的事情……不是那么多! 在C方面:

 ComplexStructure Java_com_main_MainActivity_listenUDP(JNIEnv* env, jclass clazz) { int i,taille; ComplexStructure myStruct; taille = -1; taille = recvfrom(socket, &myStruct, sizeof(ComplexStructure ), 0, &rcvAddr, &sizeOfSock); if(taille != -1) { return myStruct; } return NULL; } 

在Java方面:

 public void getFromUDP() { ComplexClass myClass = new ComplexClass(); myClass = listenUDP(); } @Override public void run() { initUDP(); getFromUDP(); } public static native ComplexClass listenUDP(); public static native void initUDP(); public static native void closeUDP(); /** Load jni .so on initialization */ static { System.loadLibrary("native-interface"); } 

编辑:我想补充一点,我的结构非常复杂:

 typedef struct{ TYPE_A myStructA; TYPE_B myStructB; TYPE_C myStructC; TYPE_D myStructD; }ComplexStructure; typedef struct{ float rad; int size; bool isEmpty; }TYPE_A; typedef struct{ float rad; bool isEmpty; float color; int temp; }TYPE_B; typedef struct{ int temp; float rain; bool isEmpty; }TYPE_C; typedef struct{ float rad; int idPerson; bool isOnTime; }TYPE_D; 

更复杂,只是一个例子向您展示它是如何!

您不能将原始C结构传递给Java并期望它将这些结构视为类。 您需要为结构创建一个类。 我看到你已经这样做了,所以你唯一需要做的就是将这个结构转换为类的实例。

Java方面的代码:

 public static native ComplexClass listenUDP(); 

将翻译为:

 JNIEXPORT jobject JNICALL Java_com_main_MainActivity_listenUDP(JNIEnv *env, jclass); 

在该C代码中,您需要使用env->FindClass();来加载ComplexClass env->FindClass(); function。 然后创建该类的新实例(如果你有零参数构造函数,它简化了问题),你需要加载一个构造函数方法签名并在env->NewObject()方法中“调用”它。 完整代码:

 jclass complexClass = env->FindClass("/com/main/ComplexClass"); jmethod constructor = env->GetMethodId(complexClass, "", "()com/main/ComplexClass"); //The name of constructor method is "" jobject instance = env->NewObject(complexClass, constructor); 

然后你需要使用env->setXXXField();设置这个类的字段env->setXXXField(); 。 如果您有更多对象作为字段并希望创建它们,则对另一个对象重复上述过程。

这看起来非常复杂,但这是在托管Java代码中使用本机C的代价。