JNI:直接缓冲读数&写作

时间:2017-05-26 08:54:46

标签: java c++ java-native-interface kotlin

我有一个小的JNI方法从屏幕上检索像素。该方法从Java接收ByteBuffer,并根据此问题how to write and read from bytebuffer passing from java to jni以C ++编写。

虽然这确实有效,但我注意到我写的第一个字节不正确,但其他字节是:

  

启动时输入长度为3 000000000239F238

     

颜色是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")

为什么第一个字节错误?我假设它与它的标志有关?但话又说回来,为什么其他人没有错呢?我不确定为什么会这样。

1 个答案:

答案 0 :(得分:2)

正如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()