如何在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的代价。