从JNI操纵ByteBuffer

gon*_*zus 16 java java-native-interface bytebuffer

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

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

任何人都可以向我指出一个有效的例子吗?提前致谢.

mab*_*aba 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);
        }
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

尝试在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;
}
Run Code Online (Sandbox Code Playgroud)

在Java端检查时,在缓冲区上设置限制.