【问题标题】:how to write and read from bytebuffer passing from java to jni如何从从java到jni的bytebuffer写入和读取
【发布时间】:2012-11-14 19:47:04
【问题描述】:

我需要有关我的 android 项目的帮助。 我想将一个缓冲区从 java 传递给 jni,我的 C++ 代码将填充数据。然后java会将它们显示在屏幕上。 我对 C++ 不太熟悉,也不知道如何写入缓冲区。

这就是我得到的。 在java中

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

本机方法

public static native void processBuffer(ByteBuffer bb);

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

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

    }

我卡在这里,我可以做双dbuf吗?还是必须是字符

说我要给这个dbuf写1,2,3,4,5,我该怎么做呢? 我在想 dbuf.put(1); ... dbuf.put(5) 但它不起作用。 填充它之后,我只是在java中调用 bb.get(position) 吗?

请有人为我澄清一下,示例将不胜感激 谢谢

这是我的本地方法表

静态 JNINativeMethod 方法表[] = {

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

除最后一个外,其他两个工作正常。

【问题讨论】:

  • IM 遇到以下问题:env->GetDirectBufferAddress(env, buffer);

标签: java android c++ android-ndk java-native-interface


【解决方案1】:

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

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

但是,如果您的本机方法被正确调用,那么无论您在做什么都可能没问题。

我卡在这里,我可以做双 dbuf 吗?还是必须是字符?

函数的返回值实际上是一个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 中调用 bb.get(position) 吗?

是的,您可以使用ByteBuffer 上的访问器方法来访问您从本机代码写入的数据。

【讨论】:

  • ty,它有效,但我有 2 个问题。首先,据我所知,这是正确的共享内存。我这样做的原因是因为数据会很大,而且我不想每次来回传递数据时都对数据进行编组。其次,我如何制作这个 jni_onload,我现在正在使用 javah。对于 onload 我试过这个, {"processBuffer", "(Ljava/nio/ByteBuffer)V", (void *) fillBuffer} , processBuffer 是来自 java 的本地方法,Ljava/nio/ByteBuffer 这是参数 bytebuffer,V 参考void,fillBuffer 指的是 C++ 函数。但它映射不正确,请您检查一下,谢谢
  • 是的,直接缓冲区是两边访问的,不复制内存;这就是为什么您不必从本机代码传回对象。
  • 谢谢,信息量很大。第二个问题Devu,你能看出我做错了什么吗?谢谢
  • 我认为你的方法签名应该是"(Ljava/nio/ByteBuffer;)V"而不是......类名后有一个分号。其余的对我来说都是正确的。
  • 我认为您应该将这些问题作为新问题发布,以便其他有经验的人看到。
猜你喜欢
  • 1970-01-01
  • 2012-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-13
  • 2011-12-21
相关资源
最近更新 更多