如何在Java和JNI之间传递ByteBuffer并进行读写操作

8

我需要帮助我的安卓项目。 我想从Java传递一个缓冲区到JNI,我的C++代码将填充数据。然后Java将在屏幕上显示它们。 我不太熟悉C++,也不知道如何写入缓冲区。

这是我得到的。 在Java中:

ByteBuffer bb = ByteBuffer.allocateDirect(216);
        IssmJni.processBuffer(bb);

本地方法


public static native void processBuffer(ByteBuffer bb);

我不使用jni_onload,因此在C++中没有javah。

static void fillBuffer(JNIEnv *env, jclass clazz, jobject buf)
    {
        double *dBuf = env->GetDirectBufferAddress(env, buf);

    }

我在这里遇到了困难,我能够使用双dbuf吗?还是必须使用char?

假设我想要将1、2、3、4、5写入这个dbuf,我该怎么做? 我考虑使用dbuf.put(1); … dbuf.put(5),但它不起作用。 在填充完毕后,在Java中我只需要调用bb.get(position)吗?

请有人为我澄清这个问题,最好能提供示例 谢谢

这是我的本地方法表

static JNINativeMethod method_table[] = {

{"fac"      ,     "(J)J" , (void *) factorial},
    {"getBuffer",     "()[D" , (void *) getBufferNative},
    //{"processBuffer", "(Ljava/nio/ByteBuffer)V", (void *) fillBuffer}};

除了最后一个之外,其他两个都没有问题。

我遇到了以下编程问题:env->GetDirectBufferAddress(env, buffer); - Deepak
1个回答

9

我不使用jni_onload,所以在C++中没有javah

这可能与你的问题无关,但你必须做其中之一。你需要在onLoad函数中进行Java到本地方法映射,或者使用javah生成JNI可以在运行时捕获的方法签名。否则,你的本地方法将永远不会被调用。

然而,如果你的本地方法被正确调用,那么你正在做的事情可能是可以的。

我卡在这里了,我可以使用双重dbuf吗?还是必须是char?

该函数的返回值实际上是一个void*,因此你可以将其转换为任何指针类型,因为它只是一个内存地址。然而,直接缓冲区的实际数据类型将是jbyte,它是signed char的typedef,因此以下内容可能最好:

jbyte *dBuf = env->GetDirectBufferAddress(env, buf);

如果我想把1,2,3,4,5写入dbuf,我该怎么做?

C/C++中访问数组中的值的符号是用[]符号,例如:

jbyte *dBuf = env->GetDirectBufferAddress(env, buf);

dBuf[0] = 63;
dBuf[1] = 127;
// ...and so on...

是的,在Java中,您可以使用ByteBuffer上的访问器方法来访问从本地代码中编写的数据。填充后,只需调用bb.get(position)即可。

谢谢,它可以工作,但我有两个问题。首先,据我所知,这是共享内存,对吗?我这样做的原因是数据将会非常庞大,我不想每次来回传递数据时都进行编组。其次,我该如何制作jni_onload呢?我现在正在使用javah。对于onload,我尝试了这个:{"processBuffer", "(Ljava/nio/ByteBuffer)V", (void *) fillBuffer},processBuffer是Java中的本地方法,Ljava/nio/ByteBuffer是参数bytebuffer,V代表void,fillBuffer指的是C++函数。但它没有正确映射,你能帮我检查一下吗?谢谢 - Lan Nguyen
1
是的,直接缓冲区在两端都可以访问而不需要复制内存;这就是为什么你不必从本地代码传回对象的原因。 - devunwired
嗨Devu,我有一个新问题,不知道你能否帮忙。假设我有一个创建名为hello的类的C++代码,在该类中有一个名为print的方法并返回字符串helloworld。如果UI端点击按钮,它将调用此打印方法,但我只想创建一个名为hello的对象,并重复使用相同的打印方法,而不是每次都创建新的hello对象。我知道我需要将对象保存为全局引用,但如果你知道如何引用下一次调用,可以给我示例代码吗?谢谢。 - Lan Nguyen
1
我认为你应该将这些作为新问题发布,这样有经验的其他人才能看到它们。 - devunwired
我遇到了以下问题,我该如何获取JNIEnv问题,请帮助我:env->GetDirectBufferAddress(env, buffer); - Deepak
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接