I have read many SO Q/A but I really can't get this to work. I need to work with a vector in C++ (a library needs it) in a JNI project. So I am calling a C++ method which initializes the vector and returns a pointer to the underlying array. Java is supposed to fill it, then call another C++ method to do elaboration. At the moment, to debug the code, doComputetion takes a ByteBuffer, but it won't later.
code is as following:
.cpp:
using namespace std;
JNIEXPORT jobject JNICALL Java_nnJNI_allocateStorage(JNIEnv * env, jobject obj, jint num)
{
vector<jfloat>* in = new vector<jfloat>(num, 40.0);
jobject jbuffer = env->NewDirectByteBuffer(in->data(), in->size() * sizeof(jfloat));
return env->NewGlobalRef(jbuffer); //I know this can be avoided
}
JNIEXPORT jobject JNICALL Java_nnJNI_doComputation(JNIEnv * env, jobject, jobject in)
{
float* f = (float*)env->GetDirectBufferAddress(in);
float* out = new float[1];
out[0] = 10;
jobject jbuffer = env->NewDirectByteBuffer(out, 1 * sizeof(jfloat));
return jbuffer;
}
java class:
public class nnJNI {
static {
System.loadLibrary("YIAnnLib");
}
private native ByteBuffer allocateStorage(int size);
private native ByteBuffer doComputation(ByteBuffer buffer);
public void demo() {
ByteBuffer buf = allocateStorage(2);
float f = buf.getFloat();
ByteBuffer b = ByteBuffer.allocateDirect(8);
b.putFloat(10); b.putFloat(12);
ByteBuffer res = doComputation(b);
float g = res.getFloat();
}
}
As you can see I initialize the array with value 40.0. In Java, float f is everything but 40.0. I really can't understand what's wrong: no one is gonna free the vector declared with new. It should stay there. I noticed a strange thing: when allocating in C++, if I declare the vector on the stack as static it seems to work. Obiviously I won't do such a bad thing.
Also the opposite doesn't work: float *f in doComputation in C++ is everything but 10 (the value it should has as initilized in Java).
Obiviously float g in Java is everything but 10. It simulates data returned by the computation.
Any hints are really appreciated.
Thanks @cubrr . It was the endianness. Just call
buf.order(ByteOrder.LITTLE_ENDIAN)
before reading and writing values IN Java. I guessed it, but I found nothing about it around, so I guessed it was automatically set according to the Operating System. It is not.