NewDirectByteBuffer 返回奇怪的值
NewDirectByteBuffer returning weird values
我读了很多 SO Q/A 但我真的无法让它工作。
我需要在 JNI 项目中使用 C++ 中的向量(库需要它)。
所以我调用了一个 C++ 方法来初始化向量和 returns 指向底层数组的指针。 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 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();
}
}
如您所见,我用值 40.0 初始化了数组。在 Java 中,float f 不是 40.0。我真的不明白哪里出了问题:没有人会释放用 new 声明的向量。它应该留在那里。我注意到一件奇怪的事情:在 C++ 中分配时,如果我将堆栈上的向量声明为静态,它似乎可以工作。明明不会做这种坏事的
反之亦然:C++ doComputation 中的 float *f 除了 10 之外的所有值(在 Java 中初始化时应具有的值)。
显然 Java 中的 float g 不是 10。它模拟计算返回的数据。
非常感谢任何提示。
谢谢@cubrr。
这是字节顺序。直接打电话
buf.order(ByteOrder.LITTLE_ENDIAN)
在读取和写入值 IN Java 之前。
我猜对了,但是我周围什么都没有发现,所以我猜它是根据操作系统自动设置的。不是。
我读了很多 SO Q/A 但我真的无法让它工作。 我需要在 JNI 项目中使用 C++ 中的向量(库需要它)。 所以我调用了一个 C++ 方法来初始化向量和 returns 指向底层数组的指针。 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 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();
}
}
如您所见,我用值 40.0 初始化了数组。在 Java 中,float f 不是 40.0。我真的不明白哪里出了问题:没有人会释放用 new 声明的向量。它应该留在那里。我注意到一件奇怪的事情:在 C++ 中分配时,如果我将堆栈上的向量声明为静态,它似乎可以工作。明明不会做这种坏事的
反之亦然:C++ doComputation 中的 float *f 除了 10 之外的所有值(在 Java 中初始化时应具有的值)。
显然 Java 中的 float g 不是 10。它模拟计算返回的数据。
非常感谢任何提示。
谢谢@cubrr。 这是字节顺序。直接打电话
buf.order(ByteOrder.LITTLE_ENDIAN)
在读取和写入值 IN Java 之前。 我猜对了,但是我周围什么都没有发现,所以我猜它是根据操作系统自动设置的。不是。