0

Javaから呼び出すことができるようにJava文字配列に変換したいUChar配列(ICU4Cライブラリから)を返すJNI関数があります。このJNI関数にアクセスすると、すべてがクラッシュしてハングするため、問題がどこにあるのかわかりませんが、logcatを含め、どこにもエラーメッセージは表示されません...デバッグが非常に困難です。

UChar配列をjcharArrayタイプに直接マップできますか?また、返品タイプとして使用できますか?または、JNI関数が入力するパラメーターとしてそれを渡すことはできますか?

これが基本的に私がやろうとしていることの抜粋です:

static jint testFunction(JNIEnv* env, jclass c, jobject obj, jcharArray chsArray,
                           int offset, int len, jcharArray dstArray) {

jchar* dst = env->GetCharArrayElements(dstArray, NULL);

if (dst != NULL) {

    UChar *str = new UChar[len];

    //populate str here from an ICU4C function

    for (int i=0; i<len; i++)
        dst[i] = str[i];      //this might be the problematic piece of code (can I issue an assignment like this?)
    }
}

env->ReleaseCharArrayElements(dstArray, dst, 0);

}

どんな助けでも大歓迎です!

ありがとう

4

4 に答える 4

1

JNIは本当に頭痛の種になる可能性があります。あなたの機能は、表面上はうまく見えます。

まず、あなたが使用していないことに注意してくださいoffset-それはコードの臭いです。

次に、UChar配列を解放していません。

第3に、C関数または割り当てループのいずれかが配列の境界を超えている可能性があります。


printこのような突然のクラッシュを見つけるのを助けるために、私はコンソールと組み合わせて古き良きステートメントをうまく使用しました。

まず、JNIGlobalクラスにprintlnメソッドを追加しました。

/** Print text or ASCII byte array prefixed with "JNI: ". Primarily for native code to output to the Java console. */
static public void println(Object val) {
    if(val instanceof byte[]) { byte[] ba=(byte[])val; val=new String(ba,0,ba.length); }
    System.out.println("JNI: "+val);
    }

次に、対応するメソッドをCコードに追加しました。

void println(JNIEnv *jep, byte *format,...) {
    va_list                             vap;
    byte                                txt[5001];
    jsize                               txtlen;
    jclass                              eCls;
    jint                                mId;
    jbyteArray                          jText;

    va_start(vap,format); vsprintf(txt,format,vap); va_end(vap);
    txtlen=(long)strlen(txt);

    if((eCls=(*jep)->FindClass(jep,"<your/package/here/JNIGlobal"))==0) {
        printf("JNI: Global class not found (Error Text: %s)\n",txt);
        return; /* give up */
        }
    if((mId=(*jep)->GetStaticMethodID(jep,eCls,"println","(Ljava/lang/Object;)V"))==0) {
        printf("JNI: Global println method not found (Error Text: %s)\n",txt);
        return; /* give up */
        }
    jText=(*jep)->NewByteArray(jep,txtlen);
    (*jep)->SetByteArrayRegion(jep,jText,0,txtlen,(void*)txt);
    (*jep)->CallStaticVoidMethod(jep,eCls,mId,jText);
    }

println(env,"Some formatted output")次に、ソースの各行を呼び出して、どこまで到達するかを確認します。私の環境(AS / 400)では、対話型実行中にJVMがクラッシュすると、コンソールが残ります。コンソールがなくなる前に出力が表示されるように、Javaコードに短い遅延を追加することをお勧めします。

だからあなたのために、そのように:

static jint testFunction(JNIEnv* env, jclass c, jobject obj,
 jcharArray chsArray, int offset, int len, jcharArray dstArray) {

/**/println("** testFunction 1");
    jchar* dst = env->GetCharArrayElements(dstArray, NULL);

/**/println("** testFunction 2");
    if (dst != NULL) {
/**/println("** testFunction 3");
        UChar *str = new UChar[len];
/**/println("** testFunction 4");

        //populate str here from an ICU4C function

/**/println("** testFunction 5");
        for (int i=0; i<len; i++)
            dst[i] = str[i];      //this might be the problematic piece of code (can I issue an assignment like this?)
        }
/**/println("** testFunction 6");
    }

    env->ReleaseCharArrayElements(dstArray, dst, 0);
/**/println("** testFunction 7");
}
于 2011-02-23T18:47:13.237 に答える
1

ICUからUChar*値を取得し、Javaに文字列を返すことを目的としている場合(「ICU4C関数からここにstrを入力」コメントに基づいてこれを想定しています)、jstringを使用しないのはなぜですか?

例えば:

jstring Java_com_mysomethingsomething_test_getAString(JNIEnv* env, jobject thiz)
{
  UChar* buf = new UChar[BUF_LEN];
  int32_t len;
  PouplateBuffer(buf, &len);     //populate str here from an ICU4C function
  jstring result = env->NewString(reinterpret_cast<jchar*>(buf), static_cast<jint>(len));
  delete [] buf;
  return result;
}

この例はもちろん単純化されていますが、UChar*からjstringへの変換を説明する必要があります。これは、UnicodeStringでも簡単に機能します。

jstring Java_com_mysomethingsomething_test_getAString(JNIEnv* env, jobject thiz)
{
  const UnicodeString result = PopulateString();
  return env->NewString(reinterpret_cast<jchar*>(result.getBuffer()), static_cast<jint>(result.length()));
}
于 2012-06-20T02:51:05.600 に答える
0

ICU4JNIは積極的に保守されていませんが、JNIからICU4Cを呼び出す例を見ることができるかもしれません。ICU4JNISVNトランクも参照してください

于 2011-02-23T18:21:55.317 に答える
0

dstArrayの長さはどれくらいですか?lenがdstArray.lengthより大きい場合、c ++は配列の境界をチェックできず、プロセスのメモリを破壊します。

于 2011-02-15T21:13:10.177 に答える