如何使用JNI将Java ByteBuffer发送到C?

den*_*yan 2 c java java-native-interface bytebuffer native

首先,我想说旧的答案不起作用(例如,下面的答案中的GetDirectBufferAddress函数现在想要一个参数),如下所示:

JNI - 带有ByteBuffer参数的本机方法

和这里,

如何写入和读取从java传递到jni的bytebuffer

如果有人帮忙会更好..

因此,我无法使用JNI正确地将我的ByteBuffer(其中一些元素已填充)从Java发送到C,并且我无法将该ByteBuffer的元素再次返回到C

我的本地功能解除:

public native int myfunc(ByteBuffer pkt);
Run Code Online (Sandbox Code Playgroud)

分配给它

private ByteBuffer pkt = ByteBuffer.allocate(1000);
Run Code Online (Sandbox Code Playgroud)

我这样称呼它:

System.out.println(myfunc(pkt));  // Doesn't works, throws exception
pkt.position(0);
System.out.println(pkt.get()); // works, when I do comment line above .println
Run Code Online (Sandbox Code Playgroud)

我的C代码如下:

JNIEXPORT jint JNICALL Java_xxx_myfunc(JNIEnv *, jobject, jobject); // header


JNIEXPORT jint JNICALL Java_xxx_myfunc(JNIEnv *env, jobject obj, jobject pkt) // function
{
  jbyte *buff = (jbyte *) env->GetDirectBufferAddress(pkt);
  // buff[0] = 0; I've also tried in this way
  return buff[0];
  //return 1; if I return 1, it returns correctly
}
Run Code Online (Sandbox Code Playgroud)

当我运行java程序时,它抛出异常.如何从C返回填充的ByteBuffer值?

编辑

A fatal error has been detected by the Java Runtime Environment:
EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x719c16b8, pid=1096, tid=1900
Run Code Online (Sandbox Code Playgroud)

Ale*_*ohn 5

要使用GetDirectBufferAddress()你必须保证pkt是直接的(你可以用isDirect()来检查).获得这样的对象的简单方法是ByteBuffer.allocateDirect().Direct ByteBuffer也可以从C++创建.

直接和间接的ByteBuffer之间的区别在Java oficial doc中有清楚的解释.

更新我看到你的更新.不,ByteBuffer.allocate(1000)不会产生DirectByteBuffer.

正如@Tom Blodget正确指出的那样,JNI 规范明确表示GetDirectBufferAddress()可以返回NULL.这有两种方式:如果pkt是间接的ByteBuffer,则调用本身不会崩溃,但即使您确定pkt是DirectByteBuffer ,也必须检查结果.