当前位置: 首页 > 面试题库 >

如何在JNI中将C结构来回传递给Java代码?

越正阳
2023-03-14
问题内容

我有一些通过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有点陌生,不知道可能是什么问题。

编辑 :我应该注意,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/)。两者都有其优缺点,选择取决于您。



 类似资料:
  • 问题内容: 我的Android应用程序中的C代码有一个复杂的结构,我想在Java端使用它。我已经在Google和stackoverflow上进行了一些研究,因此我从C结构创建了Java类,但是现在如何在Java中获取它。 我已经找到了有关在类中创建指针并在C端使用它的信息: 但是我不明白它是如何工作的… 在上面,您可以找到我到目前为止所做的……还不算太多!在C端: 在Java方面: 编辑:我想补充

  • 我正在使用基于WebRTC的C代码库为Android开发一个实时通信应用程序(视频和音频)。我使用SWIG生成一个JNI桥,以从Java访问本机代码。调用的行为是通过在应用程序层中定义并在结构中传递给库代码的许多回调函数来确定的。传递这些回调的函数如下所示:

  • 我只是在尝试一些基本的Uber Cadence示例。我遇到了如下问题:我有一个接收结构作为参数并更改值并返回修改后的结构的活动。当执行workflow.It显示默认values.Code片段时,我无法获得修改后的值,我尝试了如下:

  • 问题内容: C部分: 开始部分: 我可以通过这种方式获取数组的第一个元素。但是如何获得带有n个元素的整个数组呢?以及如何安全地释放它们? 问题答案: 首先,即使您正在使用Go,添加cgo时也不再存在任何“安全”。由您决定何时以及如何释放内存,就像使用C进行编程一样。 在go中使用C数组的最简单方法是通过数组将其转换为切片: 最大大小的数组实际上并未分配,但是Go需要恒定大小的数组,并且要足够大。该

  • 问题内容: 我有一些如下的JavaScript代码: 我收到未定义的错误,在使用该功能之前,一切都在工作。 我希望一段时间后调用我的函数。我该怎么办? 问题答案: setTimeout(function() { postinsql(topicId); }, 4000) 您需要将匿名函数作为参数而不是字符串作为参数,后一种方法甚至不符合ECMAScript规范,但浏览器比较宽松。这是正确的解决方案,

  • 我为什么要这样做?因为lambda表达式生成的ClosureType不是默认可构造的。通过这个“技巧”,我可以默认构造这样的closureType。 此外,模板参数的要求是,它必须为空=>