如何在 Android NDK 上使用 JNI 在 C 和 Java 之间传递复杂的结构
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10300039/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to pass a complex structure between C and Java with JNI on Android NDK
提问by Bibu
I have a complex strucutre in the C code on my Android application and I would like to use it in the Java side. I've done some research with google and in stackoverflow, so I've created the java class from my C strucutre, but now how to get it in Java.
我的 Android 应用程序的 C 代码中有一个复杂的结构,我想在 Java 端使用它。我在 google 和 stackoverflow 中做了一些研究,所以我从我的 C 结构创建了 java 类,但现在如何在 Java 中获取它。
I've found these informations, about making a pointer in the class and use this on the C side :
我找到了这些信息,关于在类中创建一个指针并在 C 端使用它:
Get the field ID : (*env)->GetFieldID(...)
Get the pointer : (*env)->GetLongField(...)
Set the pointer : (*env)->SetLongField(...)
But I don't understand how it really works ...
但我不明白它是如何工作的......
Above, you can find what I've done until now ... not so much ! On the C side :
在上面,你可以找到我到目前为止所做的......不是那么多!在 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;
}
And on the Java side :
在 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");
}
EDIT : I want to add that my structure is very complex like that :
编辑:我想补充一点,我的结构非常复杂:
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;
Even more complex, just an example to show you how it is !
更复杂的,只是一个例子来告诉你它是怎么回事!
采纳答案by Jakub Zaverka
You cannot pass raw C structs into Java and expect it to treat these structs as classes. You need to create a class for your struct. I see you already did that, so the only thing you need to do is to convert this struct into an instance of the class.
您不能将原始 C 结构传递给 Java 并期望它将这些结构视为类。您需要为您的结构创建一个类。我看到您已经这样做了,因此您唯一需要做的就是将此结构转换为类的实例。
The code on the Java side:
Java端的代码:
public static native ComplexClass listenUDP();
will translate to:
将翻译成:
JNIEXPORT jobject JNICALL Java_com_main_MainActivity_listenUDP(JNIEnv *env, jclass);
In that C code, you need to load the ComplexClass using the env->FindClass();
function. Then to create a new instance of that class (it simplifies matters if you have zero-parameter constructor), you need to load a constructor method signature and "invoke" it in the env->NewObject()
method. Full code:
在该 C 代码中,您需要使用该env->FindClass();
函数加载 ComplexClass 。然后要创建该类的新实例(如果您有零参数构造函数,它会简化问题),您需要加载构造函数方法签名并在env->NewObject()
方法中“调用”它。完整代码:
jclass complexClass = env->FindClass("/com/main/ComplexClass");
jmethod constructor = env->GetMethodId(complexClass, "<init>", "()com/main/ComplexClass"); //The name of constructor method is "<init>"
jobject instance = env->NewObject(complexClass, constructor);
Then you need to set the fields of this class using env->setXXXField();
. If you have more objects as fields and want to alse create them, then repeat the above process for another object.
然后您需要使用env->setXXXField();
. 如果您有更多的对象作为字段并且还想创建它们,则对另一个对象重复上述过程。
This looks very complicated, but that's the price for using native C in managed Java code.
这看起来非常复杂,但这就是在托管 Java 代码中使用本机 C 的代价。