NewDirectByteBuffer, возвращающий странные значения
Я прочитал много SO Q/A, но я действительно не могу заставить это работать. Мне нужно работать с вектором в C++ (библиотека нуждается в этом) в проекте JNI. Поэтому я вызываю метод C++, который инициализирует вектор и возвращает указатель на базовый массив. Предполагается, что Java заполнит его, а затем вызовет другой метод C++ для проработки. В данный момент для отладки кода doComputetion использует ByteBuffer, но не будет позже.
код выглядит следующим образом:
.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-класс:
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();
}
}
Как видите, я инициализирую массив значением 40.0. В Java float f - это все, кроме 40.0. Я действительно не могу понять, что не так: никто не освободит вектор, объявленный с новым. Это должно остаться там. Я заметил странную вещь: при выделении в C++, если я объявляю вектор в стеке статическим, он, кажется, работает. Очевидно, я не буду делать такую плохую вещь.
Также не работает обратное: float * f в doComputation в C++ - это все, кроме 10 (значение, которое оно должно иметь как инициализированное в Java).
Очевидно, что float g в Java - это все, кроме 10. Он имитирует данные, возвращаемые вычислениями.
Любые советы действительно приветствуются.
1 ответ
Спасибо @cubrr . Это был порядок байтов. Просто позвони
buf.order(ByteOrder.LITTLE_ENDIAN)
перед чтением и записью значений в Java. Я догадался об этом, но ничего вокруг не нашел, поэтому предположил, что он автоматически устанавливается в соответствии с операционной системой. Это не.