在Java和C之间发送int []

rbc*_*bcc 13 c java java-native-interface android android-ndk

我在Android中有一些图像处理Java代码,它们作用于两个大的int数组.大多数时候,Java足够快,但我需要通过JNI和NDK使用C来加速一些操作.

我知道我可以将数据从int数组传递给C的唯一方法是使用ByteBuffer.allocateDirect创建一个新缓冲区,将数据复制到该缓冲区,然后使C代码作用于缓冲区.

但是,我无法看到任何方法可以在Java中操作此缓冲区中的数据,就像缓冲区是int []或byte []一样.例如,对新创建的缓冲区调用ByteBuffer.array()将失败.有没有办法让这项工作?

我的内存有限,想要减少我需要的阵列/缓冲区数量.例如,如果我可以使用IntBuffer.wrap(new int [...])创建缓冲区,然后直接用Java操作支持缓冲区的数组,那将是很好的但是我不能这样做因为似乎唯一的事情似乎是在这里为JNI工作的是ByteBuffer.allocateDirect.

有没有其他方法在C和Java之间来回发送数据?我可以以某种方式在C端分配内存并让Java直接发送数据到那里吗?

编辑:比较缓冲区使用与int []使用的基准:

int size = 1000;
IntBuffer allocateDirect = java.nio.ByteBuffer.allocateDirect(4 * size).asIntBuffer();
for (int i = 0; i < 100; ++i)
{
  for (int x = 0; x < size; ++x)
  {
    int v = allocateDirect.get(x);
    allocateDirect.put(x, v + 1);
  }
}

int[] intArray = new int[size];
for (int i = 0; i < 100; ++i)
{
  for (int x = 0; x < size; ++x)
  {
    int v = intArray[x];
    intArray[x] = v + 1;
  }
}
Run Code Online (Sandbox Code Playgroud)

在Droid手机上,缓冲版需要大约10秒才能完成,阵列版需要大约0.01秒.

Bri*_*n D 17

http://java.sun.com/docs/books/jni/html/objtypes.html,使用JNI的Get/Release<TYPE>ArrayElements(...)

在这个例子中,我将传递一个数组(为了参数,它是int array = new int[10],然后用0-9填充它

 JNIEXPORT jint JNICALL 
 Java_IntArray_doStuffArray(JNIEnv *env, jobject obj, jintArray arr)
 {

     // initializations, declarations, etc
     jint *c_array;
     jint i = 0;

     // get a pointer to the array
     c_array = (*env)->GetIntArrayElements(env, arr, NULL);

     // do some exception checking
     if (c_array == NULL) {
         return -1; /* exception occurred */
     }

     // do stuff to the array
     for (i=0; i<10; i++) {
         c_array[i] = i;
     }

     // release the memory so java can have it again
     (*env)->ReleaseIntArrayElements(env, arr, c_array, 0);

     // return something, or not.. it's up to you
     return 0;
 }
Run Code Online (Sandbox Code Playgroud)

学习3.3节,特别是3.3.2 - 这将允许你在java的内存中获取指向数组的指针,修改它并释放它,实际上允许你用本机代码修改数组.

我刚刚在我自己的项目中使用它(使用短数组)并且效果很好:)

  • 获取count int arrayLength =(*env) - > GetArrayLength(env,arr); (2认同)

Jas*_*run 5

如果使用直接分配的缓冲区,则可以使用该GetDirectBufferAddress函数直接从C访问后备阵列.这可以防止复制该区域的区域.

您可以直接操作返回的地址,就像使用普通的C数组一样,它将直接修改Java直接分配的缓冲区.

然后,作为ephemient状态,您可以使用ByteBuffer.asIntBuffer()和系列以模拟各种Java基元的数组的方式访问缓冲区.

http://download.oracle.com/javase/1.4.2/docs/guide/jni/jni-14.html