繁体   English   中英

Android通过jni将大型float数组从本机传递到Java。 如果超过一定大小会出现错误

[英]Android passing large float arrays from native to java via jni. Getting error if over certain size

我想在整个float和[100000]之外的任何地方传递一个大型的float数组。 我有一个安装程序成功传递了大小为212的数组。但是任何较大的安装程序都会崩溃,并在logcat中给出以下错误消息:

“致命信号11(SIGSEGV)位于0xbe949000(代码= 1)”

我的密码

本机功能

NIEXPORT jfloatArray JNICALL  Java_carron_graphics_benchmark_NativeWrapper_getArrayNative(JNIEnv * env, jclass cls) {

    int tempSize = mParticleSystem->mSizeOfSystem*2;

    jfloat cArray[tempSize];
    jsize len = sizeof(cArray);

    jfloatArray jArray = (*env).NewFloatArray(len);

    if (jArray != NULL) {

        jint i;

        for (i = 0; i < tempSize; i++) {
            cArray[i] = mParticleSystem->mParticlePositions[i];
        }
        (*env).SetFloatArrayRegion(jArray, 0, len, cArray);
    }
    return jArray;
}

Java非常简单地获取数组。 如果我创建并传递了一个大于212的float数组,尽管出现了如上所述的错误。

float tempArray[] = NativeWrapper.getArrayNative();

有没有人遇到这个问题,或者可以看到我如何解决这个限制? 我也很抱歉,如果这个问题已经得到回答,我找不到这个特定问题或答案。 任何帮助将不胜感激 :)

编辑:

用于更新全局jfloatArray以避免在频繁通过jni提取数组时避免垃圾回收器。

static jfloatArray gArray = NULL;

JNIEXPORT jfloatArray JNICALL Java_carron_graphics_benchmark_NativeWrapper_getArrayNative(JNIEnv * env, jclass cls)  {
    int arrayLength = mParticleSystem->mSizeOfSystem*2;

    if (gArray == NULL)
    {
        // create array
        jfloatArray jArray;
        jArray = env->NewFloatArray(arrayLength);
        gArray = (jfloatArray)env->NewGlobalRef(jArray);
    }

    // Update global 
    env->SetFloatArrayRegion(gArray, 0, arrayLength, mParticleSystem->mParticlePositions);

    return gArray;
}

您的代码的问题是堆栈的大小受到限制。 您不能在其中放置大型数组( jfloat cArray[tempSize]变量)。 如果要创建大型数组,请像Alex所示那样在堆上进行。

如果mParticleSystem->mParticlePositions是浮点数组,则此代码会更好:

int tempSize = mParticleSystem->mSizeOfSystem*2;
jfloatArray jArray = env->NewFloatArray(tempSize);

if (jArray != NULL)
{
    env->SetFloatArrayRegion(jArray, 0, tempSize, mParticleSystem->mParticlePositions);
}
return jArray;

如果不是float数组,则使用以下代码,无需创建其他float数组:

int tempSize = mParticleSystem->mSizeOfSystem*2;
jfloatArray jArray = env->NewFloatArray(tempSize);

if (jArray != NULL)
{
    if (float* ptr = env->GetFloatArrayElements(jArray, NULL))
    {
        for (int i=0; i<tempSize; i++)
        {
            ptr[i] = mParticleSystem->mParticlePositions[i];
        }
        env->ReleaseFloatArrayElements(jArray, ptr, JNI_COMMIT);
    }
}

return jArray;

编辑

要将jArray存储在其他位置(例如全局),请执行以下操作:

static jfloatArray gArray = NULL;

jfloatArray fun(...)
{
    jfloatArray jArray;

    if (gArray == NULL)
    {
        // create array
        jArray = env->NewFloatArray(tempSize);
        gArray = (jfloatArray)env->NewGlobalRef(jArray);
    }
    else
    {
        jArray = gArray;
    }

    // ... here fill/modify jArray
    // SetFLoatArrayRegion/GetFloatArrayElemeents/ReleaseFloatArrayElements

    return jArray;
}

完成后释放内存:

void freeArray(...)
{
    env->DeleteGlobalRef(gArray);
    gArray = NULL;
}

您的代码无法编译:您可能有

jfloat *cArray = new jfloat[tempSize];

在您的编译代码中。

您的代码中的错误是在调用NewFloatArray()。 您应该调用NewFloatArray(tempSize),而不是(sizeof(cArray))。

另请注意,无需使用mParticleSystem-> mParticlePositions的中间副本。 如果它是一个float数组,则可以将其简单地用于SetFloatArrayRegion()。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM