I need to pass a (direct) ByteBuffer
to native functions that will read/write from/into the buffer. Once these operations are completed, I would like to access the ByteBuffer
from Java code using the regular functions; in particular, limit()
and position()
should reflect the current state of the buffer.
Since JNI will use GetDirectBufferAddress()
to directly access the underlying buffer, I am assuming I should call flip ()
/ limit()
/ position()
after I am done reading / writing. However, I have been unable to make this work. For example, after I read a couple of bytes into the buffer from C, and set its limit and position accordingly, I cannot query those bytes from Java; Java's idea of the buffer limit and position are not consistent with what I did in the C code.
Can anybody point me to a working example of this? Thanks in advance.
You could let your native method return the number of written bytes. Then update the ByteBuffer accordingly on the Java side.
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
Trying out to set the limit value on the C side is working too so I don't know why you have problems with it.
Naive implementation (nothing cached etc.):
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;
}
The limit is set on the buffer when inspecting on Java side.