Подтвердить что ты не робот

Манипуляция ByteBuffer от JNI

Мне нужно передать (direct) ByteBuffer на нативные функции, которые будут читать/записывать из/в буфер. Как только эти операции будут завершены, я хотел бы получить доступ к ByteBuffer из кода Java, используя обычные функции; в частности, limit() и position() должны отражать текущее состояние буфера.

Поскольку JNI будет использовать GetDirectBufferAddress() для прямого доступа к базовому буферу, я предполагаю, что я должен называть flip ()/limit()/position() после того, как я закончил чтение/запись. Однако я не смог выполнить эту работу. Например, после того, как я прочитал пару байтов в буфере от C и задал его лимит и позицию соответственно, я не могу запросить эти байты из Java; Идея Java о пределе и позиции буфера не согласуется с тем, что я сделал в коде C.

Может ли кто-нибудь указать мне на рабочий пример? Спасибо заранее.

4b9b3361

Ответ 1

Вы можете позволить вашему собственному методу вернуть количество записанных байтов. Затем обновите ByteBuffer соответственно на стороне Java.

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);
        }
        ...
    }
}

Edit

Попытка установить предельное значение на стороне 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.