从JNI操作ByteBuffer

18

我需要将一个(直接) ByteBuffer 传递给从中读取/写入缓冲区的本地函数。一旦这些操作完成,我想要使用常规函数从Java代码中访问ByteBuffer;特别是limit()position()应该反映缓冲区的当前状态。

由于JNI将使用GetDirectBufferAddress()直接访问底层缓冲区,因此我假设在读取/写入完成后应该调用flip()/limit()/position()。然而,我无法使其工作。例如,在从C中将几个字节读入缓冲区并相应地设置其限制和位置之后,我不能从Java中查询这些字节;Java对缓冲区限制和位置的理解与我在C代码中所做的不一致。

有人能指向一个可行的例子吗?提前感谢。


应该可以工作,这就是整个想法。您设置了什么位置和限制值,以及如何设置,在Java中看到了什么值? - user207421
1个回答

19
您可以让本地方法返回已写入字节的数量,然后在Java端相应地更新ByteBuffer。
public class SomeClass {
    /**
     * @param buffer input/output buffer
     * @return number of bytes written to buffer
     */
    private native int nativeMethod(ByteBuffer buffer);

    public void myMethod() {
        ByteBuffer buffer = ByteBuffer.allocateDirect(100);
        int written = nativeMethod(buffer);
        if (written > 0) {
            buffer.limit(written);
        }
        ...
    }
}

编辑

尝试在C端设置限制值也可以正常工作,所以我不知道你为什么会遇到问题。

朴素实现(没有缓存等):

static jint nativeMethod(JNIEnv *env, jobject obj, jobject buffer) {
    jclass cls = env->GetObjectClass(buffer);
    jmethodID mid = env->GetMethodID(cls, "limit", "(I)Ljava/nio/Buffer;");
    char *buf = (char*)env->GetDirectBufferAddress(buffer);
    jlong capacity = env->GetDirectBufferCapacity(buffer);
    int written = 0;

    // Do something spectacular with the buffer...

    env->CallObjectMethod(buffer, mid, written);
    return written;
}

检查Java端时,缓冲区的限制已设置。


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