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. Я догадался об этом, но ничего вокруг не нашел, поэтому предположил, что он автоматически устанавливается в соответствии с операционной системой. Это не.

Другие вопросы по тегам