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.
A ByteBuffer is created via the the two static factory methods: allocate(int) this will allocate a HeapByteBuffer with the capacity specified by the int argument. allocateDirect(int) this will allocate a DirectByteBuffer with the capacity specified by the int argument.
ByteBuffer holds a sequence of integer values to be used in an I/O operation. The ByteBuffer class provides the following four categories of operations upon long buffers: Absolute and relative get method that read single bytes. Absolute and relative put methods that write single bytes.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With