You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过JNI实现Java三维数组到C++的传递与结果返回

JNI传递三维float数组问题与实现

问题描述

我目前在做项目开发,需要在C侧处理三维数组的计算逻辑:先把三维数组从Java端传到C端,计算完成后再把结果返回Java。我用JNI做两端交互,但接触JNI时间短,相关经验不足,现在正在写测试示例给后续开发做参考。
目前我已经跑通了二维数组的传递逻辑,二维数组的实现参考了现有公开方案,但三维数组的传递一直没调通。

已验证可用的二维数组传递C++代码

float** testFunction(float **a)
{
    printf("Hello from JNI!\n");
    printf("Point at %d,%d is: %f\n", 1, 2, a[1][2]);

    return a[1][2];
}
jfloat JNICALL Java_JNIArray_integrateWithTrapezoid(JNIEnv *env, jobject thisObj, jobjectArray jarr)
{
    int sizex = env->GetArrayLength(jarr);
    jfloatArray dim = (jfloatArray)env->GetObjectArrayElement(jarr, 0);
    int sizey = env->GetArrayLength(dim);
    float **localArray;

    localArray = new float *[sizex];

    for (int i = 0; i < sizex; i++)
    {
        jfloatArray oneDim = (jfloatArray)env->GetObjectArrayElement(jarr, i);
        jfloat *element = env->GetFloatArrayElements(oneDim, 0);
        localArray[i] = new float[sizey];

        for (int j = 0; j < sizey; j++)
        {
            localArray[i][j] = element[j];
        }
    }

    return testFunction(localArray);
}

如果有人能提供三维数组传递的实现思路我会非常感谢,目前我对这部分的实现逻辑还没理清楚,如果我漏了什么必要的信息可以随时提。
谢谢。


更新:已跑通的三维数组传递实现

在其他开发者的帮助下,我已经完成了可正常运行的三维数组传递方案,代码如下:

void trapezoidalintegral(float ***a)
{
    printf("Hello from JNI!\n");
    printf("Point at %d, %d, %d is: %f\n", 1, 2, 2, a[1][2][2]);
    return;
}

float *thirdLevel(JNIEnv *env, jfloatArray arr)
{
    jsize len = env->GetArrayLength(arr);
    float *ret = new float[len];
    env->GetFloatArrayRegion(arr, 0, len, ret);
    return ret;
}

float **secondLevel(JNIEnv *env, jobjectArray arr)
{
    jsize len = env->GetArrayLength(arr);
    float **ret = new float *[len];
    for (int i = 0; i < len; i++)
    {
        jobject item = env->GetObjectArrayElement(arr, i);
        ret[i] = thirdLevel(env, (jfloatArray)item);
        env->DeleteLocalRef(item);
    }
    return ret;
}

float ***firstLevel(JNIEnv *env, jobjectArray arr)
{
    jsize len = env->GetArrayLength(arr);
    float ***ret = new float **[len];
    for (int i = 0; i < len; i++)
    {
        jobject item = env->GetObjectArrayElement(arr, i);
        ret[i] = secondLevel(env, (jobjectArray)item);
        env->DeleteLocalRef(item);
    }
    return ret;
}

JNIEXPORT jobjectArray JNICALL Java_JNIArray_integrateWithTrapezoid(JNIEnv *env, jobject thisObj, jobjectArray jarr)
{
    float ***returningArray;

    returningArray = firstLevel(env, jarr);

    trapezoidalintegral(returningArray);

    jclass *pClass;
    jclass cls1;
    jclass jcls1;
    jclass jcls2;
    jobject obj2;

    cls1 = env->GetObjectClass(thisObj);
    // jfieldID fid1 = env->GetFieldID(cls1, "ptr", "J");
    // pClass = (jclass *)env->GetLongField(thisObj, fid1);

    jcls1 = env->FindClass("[[F");
    jcls2 = env->FindClass("[F");

    jobjectArray array1 = env->NewObjectArray(3, jcls1, NULL);

    for (int i = 0; i < 3; i++)
    {
        jobjectArray array2 = env->NewObjectArray(3, jcls2, NULL);

        for (int j = 0; j < 3; j++)
        {
            jfloatArray array3 = env->NewFloatArray(3);
            env->SetFloatArrayRegion(array3, 0, 3, returningArray[i][j]);
            env->SetObjectArrayElement(array2, j, array3);
        }

        env->SetObjectArrayElement(array1, i, array2);
    }

    env->DeleteLocalRef(cls1);
    env->DeleteLocalRef(jcls1);
    env->DeleteLocalRef(jcls2);

    return array1;
}

这个实现把数组解析拆成了三层函数,分别处理最外层三维数组、中间二维数组、最内层一维float数组,逐层把Java的数组对象转换成C++侧的三级指针;计算完成后再反过来逐层构造Java侧的三维数组对象返回,每一层取完数组元素就及时删掉局部引用,避免JNI局部引用溢出。

内容的提问来源于stack exchange,提问作者Nic Bolton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 08:09:42