JNI:直接缓冲区读写

我有一个小的JNI方法来从屏幕上检索一个像素。 该方法接收来自Java的ByteBuffer,并根据这个问题在C ++ 中写入如何写入和读取从bytebuffer从java传递到jni 。

虽然这个工作,我注意到我写的第一个字节是不正确的,但其他人是:

输入长度从000000000239F238开始为3

颜色是202,97,79

值在Java读取:-54,97,79

这是我的程序的输出。

C ++代码:

JNIEXPORT void JNICALL Java_capturePixel(JNIEnv * env, jobject clz, jobject buffer) { jbyte* bufferStart = static_cast<jbyte*>(env->GetDirectBufferAddress(buffer)); jlong inputLength = env->GetDirectBufferCapacity(buffer); HDC hScreenDC = GetDC(nullptr); std::cout << "Input length is " << inputLength << " at start " << &bufferStart << std::endl; COLORREF pixel = GetPixel(hScreenDC, 100, 20); int r = GetRValue(pixel); int g = GetGValue(pixel); int b = GetBValue(pixel); std::cout << "Color is " << r << ", " << g << ", " << b << std::endl; bufferStart[0] = r; bufferStart[1] = g; bufferStart[2] = b; } 

我的Java代码(其实Kotlin):

 val r = buffer.get() val g = buffer.get() val b = buffer.get() println("values read in java: $r, $g, $b") 

为什么第一个字节错了? 我假设它必须处理它的标志? 但是,为什么其他人没有错呢? 我不知道为什么会发生这种情况。

正如Richard在提到的评论中所说的,它与字节的符号有关。 这两个值是正确的,因为它们不会超过127; RGB是无符号的,范围从0-255,而有符号的字节范围从-128到127。

缓冲区中的字节是正确的,但是java的buffer.get()读取它的签名。

解决这个问题的方法是调用Byte.toUnsignedInt(…) (Java API)读取字节。

或者,您可以在Kotlin中创建一个扩展方法:

 fun Byte.toUnsigned(): Int = this.toInt() and 0xff 

然后你可以使用这个来调用缓冲区上的get():

 val r = buffer.get().toUnsigned() val g = buffer.get().toUnsigned() val b = buffer.get().toUnsigned()