如何使用JNI返回2D长数组 [英] How to return 2D long array with JNI

查看:42
本文介绍了如何使用JNI返回2D长数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个代码,必须使用JNI将长数组从C返回到Java.但是无论我尝试什么,方法(* env)-> FindClass都会返回NULL.

这是我的代码:

// Returns a 2D long array from C to Java
JNIEXPORT jobjectArray JNICALL Java_awax_tools_AcquisitionWrapper_startAcquisition (JNIEnv *env, jobject obj) {

    // (...) Acquisition code

    // The 2D long array to return
    long** primitive2DArray = data;

    // Get the long array class
    jclass longArrayClass = (*env)->FindClass(env, "[java/lang/Long");

    // Check if we properly got the long array class
    if (longArrayClass == NULL) {
        // Ooops
        return NULL;
    }

    // Create the returnable 2D array
    jobjectArray myReturnable2DArray = (*env)->NewObjectArray(env, (jsize) length1D, longArrayClass, NULL);

    // Go through the firs dimension and add the second dimension arrays
    for (unsigned int i = 0; i < length1D; i++) {
        jlongArray longArray = (*env)->NewLongArray(env, length2D);
        (*env)->SetLongArrayRegion(env, longArray, (jsize) 0, (jsize) length2D, (jlong*) primitive2DArray[i]);
        (*env)->SetObjectArrayElement(env, myReturnable2DArray, (jsize) i, longArray);
        (*env)->DeleteLocalRef(env, longArray);
    }

    // Return a Java consumable 2D long array
    return myReturnable2DArray;
}

我也尝试过:

(*env)->FindClass(env, "[L")
(*env)->FindClass(env, "[Long")
(*env)->FindClass(env, "[java.lang.Long")

但是它们似乎都不起作用.

解决方案

如果您确实想要java.lang.Long对象的数组,则必须编写[Ljava/lang/Long;.如果创建一个数组,则会得到[[Ljava/lang/Long;,在Java端为Long[][].

但是,这效率很低.您必须在该数组内为每个数字创建一个对象.使用Long.valueOf 可以为您提供缓存的对象,但我怀疑该数组中的许多值是否适合带符号的字节.

您应该使用原始的long值而不是Long对象.除了代码第一行之外的所有内容都已在执行此操作.原始long s数组的正确内部名称是[J:

jclass longArrayClass = (*env)->FindClass(env, "[J");

其余代码正确无误,该方法将返回long[][].


但是要当心:您没有在说要使用哪个平台,但是例如在Windows上,这仍然行不通:long只是变相的int,它也是32位值.另一方面,jlong始终具有64位,并且正是由于这个原因而被类型定义为long long.您会盲目地投射指针,因此您的代码将尝试复制实际上两倍的数据.

I'm writing a code which must return a long array from C to java using JNI. But the method (*env)->FindClass returns NULL whatever I tried.

Here is my code :

// Returns a 2D long array from C to Java
JNIEXPORT jobjectArray JNICALL Java_awax_tools_AcquisitionWrapper_startAcquisition (JNIEnv *env, jobject obj) {

    // (...) Acquisition code

    // The 2D long array to return
    long** primitive2DArray = data;

    // Get the long array class
    jclass longArrayClass = (*env)->FindClass(env, "[java/lang/Long");

    // Check if we properly got the long array class
    if (longArrayClass == NULL) {
        // Ooops
        return NULL;
    }

    // Create the returnable 2D array
    jobjectArray myReturnable2DArray = (*env)->NewObjectArray(env, (jsize) length1D, longArrayClass, NULL);

    // Go through the firs dimension and add the second dimension arrays
    for (unsigned int i = 0; i < length1D; i++) {
        jlongArray longArray = (*env)->NewLongArray(env, length2D);
        (*env)->SetLongArrayRegion(env, longArray, (jsize) 0, (jsize) length2D, (jlong*) primitive2DArray[i]);
        (*env)->SetObjectArrayElement(env, myReturnable2DArray, (jsize) i, longArray);
        (*env)->DeleteLocalRef(env, longArray);
    }

    // Return a Java consumable 2D long array
    return myReturnable2DArray;
}

I also tried with :

(*env)->FindClass(env, "[L")
(*env)->FindClass(env, "[Long")
(*env)->FindClass(env, "[java.lang.Long")

But none of them seems to work.

解决方案

If you really want an array of java.lang.Long objects, you have to write [Ljava/lang/Long;. If you create an array of those, you get [[Ljava/lang/Long; which would be Long[][] on the Java side.

However, this is terribly inefficient. You have to create an object for every single number inside that array. Using Long.valueOf can give you cached objects but I doubt that many values inside that array fit into a signed byte.

Instead of Long objects, you should use primitive long values. Everything except the first line of your code is already doing that. The correct internal name for an array of primitive longs is [J:

jclass longArrayClass = (*env)->FindClass(env, "[J");

The rest of your code is correct and the method will return a long[][].


But watch out: You aren't saying anything about which platform you're using, but on Windows for example, this still won't work: A long there is just an int in disguise, it's also a 32 bit value. A jlong on the other hand always has 64 bits and is typedef'd to a long long for exactly that reason. You're blindly casting the pointers, so your code would try to copy twice as much data as you actually have.

这篇关于如何使用JNI返回2D长数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆