从 JNI 操作字节缓冲区

2022-09-02 21:54:45

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

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

任何人都可以给我指出一个工作的例子吗?提前致谢。


答案 1

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


答案 2

推荐