我有一些通过JNI调用的C函数,这些函数带有指向结构的指针,还有一些其他函数将分配/释放指向相同类型结构的指针,以便处理包装程序更加容易。令人惊讶的是,JNI文档很少介绍如何处理C结构。
我的C头文件如下所示:
typedef struct _MyStruct { float member; } MyStruct; MyStruct* createNewMyStruct(); void processData(int *data, int numObjects, MyStruct *arguments);
相应的JNI C包装文件包含:
JNIEXPORT jobject JNICALL Java_com_myorg_MyJavaClass_createNewMyStruct(JNIEnv *env, jobject this) { return createNewMyStruct(); } JNIEXPORT void JNICALL Java_com_myorg_MyJavaClass_processData(JNIEnv *env, jobject this, jintArray data, jint numObjects, jobject arguments) { int *actualData = (*env)->GetIntArrayElements(env, data, NULL); processData(actualData, numObjects, arguments); (*env)->ReleaseIntArrayElements(env, data, actualData, NULL); }
…最后是对应的Java类:
public class MyJavaClass { static { System.loadLibrary("MyJniLibrary"); } private native MyStruct createNewMyStruct(); private native void processData(int[] data, int numObjects, MyStruct arguments); private class MyStruct { float member; } public void test() { MyStruct foo = createNewMyStruct(); foo.member = 3.14159f; int[] testData = new int[10]; processData(testData, 10, foo); } }
不幸的是,此代码在点击后立即使JVM崩溃createNewMyStruct()。我对JNI有点陌生,不知道可能是什么问题。
createNewMyStruct()
编辑 :我应该注意,C代码非常原始,经过了充分的测试,并且是从运行中的iPhone项目移植而来的。另外,该项目使用的是Android NDK框架,该框架使您可以从JNI中的Android项目运行本机C代码。但是,我认为这并不是严格意义上的NDK问题……我看来这似乎是JNI安装/初始化错误。
您需要创建一个具有与C结构相同成员的Java类,然后通过env-> GetIntField,env-> SetIntField,env-> GetFloatField,env-> SetFloatField等方法在C代码中“映射”它们- 简而言之,大量的体力劳动,希望已经有可以自动执行的程序:JNAerator(http://code.google.com/p/jnaerator)和SWIG(http://www.swig.org/)。两者都有其优缺点,选择取决于您。