从JNI操纵ByteBuffer

时间:2012-07-04 12:52:13

标签: java java-native-interface bytebuffer

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

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

有人能指出我的一个实际例子吗?提前谢谢。

1 个答案:

答案 0 :(得分:15)

您可以让您的本机方法返回写入的字节数。然后在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端检查时,在缓冲区上设置了限制。