如何使用 JNI 将 Java ByteBuffer 发送到 C?
Posted
技术标签:
【中文标题】如何使用 JNI 将 Java ByteBuffer 发送到 C?【英文标题】:How to send Java ByteBuffer to C using JNI? 【发布时间】:2017-11-08 08:56:33 【问题描述】:首先,我想说旧的答案现在不起作用(例如,下面答案中的 GetDirectBufferAddress 函数现在需要一个参数),如下所示:
JNI - native method with ByteBuffer parameter
这里,
how to write and read from bytebuffer passing from java to jni
如果有人帮忙会更好..
因此,我无法使用 JNI 从 Java 将填充了一些元素的 ByteBuffer 正确发送到 C,并且我无法再次将该 ByteBuffer 的元素返回给 C
我的原生函数声明:
public native int myfunc(ByteBuffer pkt);
为其分配
private ByteBuffer pkt = ByteBuffer.allocate(1000);
我这样称呼它:
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
我的 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
当我运行 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
【问题讨论】:
你能发布堆栈跟踪吗? @Emax 我正在使用不同的电脑进行编码,但将问题编辑为跟踪的开始 好的,但是你在哪里分配pkt
?您的问题是缺少minimal reproducible example。顺便说一句,所有示例都表明您必须发送env
作为第一个参数env->GetDirectBufferAddress(env, buf)
编译时是否有警告?
@Stargateur 抱歉我忘记了,但我现在编辑了分配行。正如我在问题中指定的那样,我无法为 GetDirectBufferAddress 函数输入两个参数。而且我不确定 buf 是什么。 buf 不是我的 pkt 参数吗?不,没有警告。我认为,如果我的函数出现问题,我无法向 Java 返回 1 值或无法打印 ByteBuffer 的第一个参数
如果您可以通过逐个访问值来生存,请看这里:github.com/mkowsiak/jnicookbook/tree/master/recipeNo040
【参考方案1】:
要使用GetDirectBufferAddress()
,您必须保证pkt 是direct(您可以使用isDirect() 进行检查)。获取此类对象的简单方法是ByteBuffer.allocateDirect()
。也可以从 C++ 创建 Direct ByteBuffer。
直接和间接ByteBuffer的区别在Javaoficial doc中有清楚的解释。
更新我看到了你的更新。不,ByteBuffer.allocate(1000)
不会产生 DirectByteBuffer。
正如@Tom Blodget 正确noted,JNI spec 明确表示GetDirectBufferAddress()
可以返回NULL。这适用于两种方式:如果 pkt 是间接 ByteBuffer,则调用本身不应崩溃,但即使您确定 pkt 是 DirectByteBuffer,您也必须检查结果。
【讨论】:
对NULL
(根据documenation)检查GetDirectBufferAddress()
的结果的“C”操作将比isDirect()
覆盖更多的案例。
@TomBlodget "C" 的事情不会检查NULL
或isDirect()
,是用户函数有责任提供正确的参数(当然函数必须在文档中明确询问这种参数) ;)【参考方案2】:
您不能使用GetDirectBufferAddress()
,除非在直接字节缓冲区上。您没有直接字节缓冲区。
【讨论】:
以上是关于如何使用 JNI 将 Java ByteBuffer 发送到 C?的主要内容,如果未能解决你的问题,请参考以下文章