如何从C函数返回值给Java调用程序?

时间:2019-07-29 06:40:24

标签: java c arrays java-native-interface bytebuffer

我有一个C函数,如下所示:

int getInfo(int index, int type, void *pValue, int valueLen);

pValue是用于保存信息值的缓冲区的地址。但是,缓冲区必须已经由调用方预先分配。

由于我相当确定我正在处理小数据,因此我将在Java托管代码中执行以下操作...

public native int callGetInfo(int index, int type, byte[] value);

...然后传递一个固定大小的字节数组,如下所示:

byte[] buf = new byte[1024];
callGetInfo(idx, t, buf);

原因是因为我读到小数据,在性能方面,使用字节数组比ByteBuffer好。

我自动生成的JNI标头如下:

JNIEXPORT jint JNICALL Java_com_testing_jni_Tester_callGetInfo (JNIEnv *, jobject, jint, jint, jbyteArray);

在我的桥接函数中,我想将pValue函数返回的getInfo的值(可能是任何类型)转换为jbyteArray,以便我可以将其返回给Java调用者。我该如何实现?

1 个答案:

答案 0 :(得分:1)

解决方案将类似于

JNIEXPORT jint JNICALL Java_com_testing_jni_Tester_callGetInfo
(JNIEnv *env, jobject obj, jint index, jint type, jbyteArray array)
{
    jboolean isCopy;

    jsize arrayLength = (*env)->GetArrayLength(env, array);
    jbyte* bufferPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
    if (! bufferPtr) {
        // got exception
        return 0;
    }

    jint rv = getInfo(index, type, bufferPtr, arrayLength);
    (*env)->ReleaseByteArrayElements(env, array, bufferPtr, 0);
    return rv;
}

还有一个调用GetPrimitiveArrayCriticalReleasePrimitiveArrayCritical可能不可用,因为未知getInfo的内容-特别是在使用这些功能时,getInfo函数无法使用执行任何阻塞的系统调用或进行长时间运行的操作。

isCopy告知是否复制了锁定的数组。如果未复制,则该函数将直接修改实际的Java数组。如果是副本,则现在将1024字节的缓冲区复制到另一个位置,并将在函数末尾复制回去。可能是您不希望发生这种情况...也许您想使用字节缓冲区代替...