JNI / C库:传递byte ptr

时间:2009-12-04 18:42:23

标签: c android java-native-interface

我的C库中有一个unsigned char*,我正在调用一个JNI导出的函数,需要用这个数据设置一个java对象,最好是byte[]

但是这个函数会经常被调用,并且需要复制很多数据。

是否可以使用ByteBuffer并将该ByteBuffer的指针分配给我的unsigned char*?或者它只是反过来工作?

我是否可以在不复制数据的情况下执行此操作?什么是访问它的最佳方式?

unsigned char*中的数据大小已知。

1 个答案:

答案 0 :(得分:4)

考虑到您提供的信息很少,这是一个可能的解决方案。

在Java方面,你会有:

package com.stackoverflow;

public class JNIQuestion
{
  static native void fillByteArray(byte[] buffer);
}

在C方面你会得到:

JNIEXPORT void JNICALL Java_com_stackoverflow_JNIQuestion_fillByteArray(JNIEnv* env, jbyteArray array)
{
  jboolean isCopy;
  jbyte* buffer = (*env)->GetByteArrayElements(env, array, &isCopy);
  jsize length = (*env)->GetArrayLength(env, array);
  jsize i;

  // do something with the buffer here, replace with something meaningful
  // PAY ATTENTION TO BUFFER OVERFLOW, DO NOT WRITE BEYOND BUFFER LENGTH
  for (i = 0; i < length; ++i)
    buffer[i] = i;

  // here it is important to use 0 so that JNI takes care of copying
  // the data back to the Java side in case GetByteArrayElements returned a copy
  (*env)->ReleaseByteArrayElements(env, buffer, 0);
}

使用直接ByteBufferByteBuffer.allocateDirect())也是一种可行的解决方案。但是,当我需要从Java端填充缓冲区中非常精确的偏移量时,我只使用直接ByteBuffer

关于性能,使用byte[]的解决方案应该是令人满意的,因为JVM可能会固定字节数组而不是在调用GetByteArrayElements()时复制它。

一般来说,您需要最小化JNI调用的数量,这意味着从C端访问对象字段或从C端分配Java将对性能产生影响。

无论如何,首先进行配置,然后进行优化。

PS:我没有尝试编译代码,可能有拼写错误。请参阅JNI GuideJNI Tutorial