-1

この記事をフォローしました。そして今、私はこのJNIコードを持っています:

extern "C"{
   JNIEXPORT jfloatArray JNICALL Java_com_jp_algi_Corelib_vector
       (JNIEnv *env, jobject clazz, jfloatArray input){
        jfloat* flt1;
        flt1  = (*env)->GetFloatArrayElements(env, input, NULL);
        if (flt1 == NULL){
            return NULL; /* exception occurred */
        }
        // do stuff to the array
        (*env)->ReleaseFloatArrayElements(env, input, flt1, 0);
        return flt1;
        //delete flt1, v;
        //env->SetFloatArrayRegion(result, 0, 1, v);
    }
}

そして、それが大丈夫かどうかをチェックするために; 私はJavaコード配列に、ログに記録する長さチェックがあり、それでも44512配列を送り返していますが、入力配列の長さの影響を受けません!! Application.mkそれでも同じですが、ビルドはOKなので、エラーが発生したと思います。

App.mk

  APP_ABI := all
  APP_STL := stlport_static

そしてandr.mk確かに:

LOCAL_PATH := $(TOP_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE    := com_jp_algi_Corelib
LOCAL_SRC_FILES := com_jp_algi_Corelib.cpp, kiss_fft.c, kiss_fftr.c
include $(BUILD_SHARED_LIBRARY)

OK私の質問は:

JNIとC++で理解できないため、JNIコードが機能せず、理由もわかりません。

誰かが私のコードを書き直す方法を教えてください。

OK私の仕事は:

  • Java配列をC++に配列を使用してのみ動作させ、Java配列に戻したい
4

1 に答える 1

2

最初は、jfloat*をJavaに戻すことはできません。このコードがJVMをクラッシュさせないのは幸運です。次に、ReleaseFloatArrayElementsを呼び出した後に配列へのポインター(つまりjfloat *)を使用することはできません。これは、この配列をJVMに返し、配列を移動したり、削除したりする可能性があるためです。

タスクに応じて更新

通常、私はこのようにします。

extern "C" {
JNIEXPORT jboolean JNICALL Java_com_jp_algi_Corelib_vector
   (JNIEnv *env, jobject clazz, jfloatArray input){
    jfloat* flt1 = NULL;
    jsize size = env->GetArrayLength(input);
    // check if array size >0 and wedont cause exception
    if(size<=0) return(JNI_FALSE);
    if(env->ExceptionCheck()) {
#ifndef NDEBUG
      env->ExceptionDescribe();
#endif
      env->ExceptionClear();
      return(JNI_FALSE);
    }
    // allocate buffer for array and get data from Java array
    flt1  = new jfloat[size];
    env->GetFloatArrayRegion(input,0,size,flt1);
    // exception check. Always use exception check
    if(env->ExceptionCheck()) {
#ifndef NDEBUG
      env->ExceptionDescribe();
#endif
      env->ExceptionClear();
      delete[] flt1;
      return(JNI_FALSE);
    }
    // do stuff to the array
    // set result to Java array and delete buffer. And exception check of course
    env->SetFloatArrayRegion(input,0,size,flt1);
    delete[] flt1;
    if(env->ExceptionCheck()) {
#ifndef NDEBUG
      env->ExceptionDescribe();
#endif
      env->ExceptionClear();
      return(JNI_FALSE);
    }
    // All is ok
    return(JNI_TRUE);
}
}

GetFloatArrayElementsを使用する場合は、元のJava配列がメモリ内で移動しないようにするため、GetArrayRegions/SetArrayRegionを使用することをお勧めします。場合によっては、他のthtreadでOutOfMemoryExceptionが発生する可能性があります。

PS:いくつかの括弧を見逃していないかどうかはわかりませんが、そうである場合は申し訳ありません

于 2013-01-11T15:54:20.480 に答える