2009-08-05 14 views
5

私はすでにそれに関する質問を掲載しましたが、その時点で私はそのアカウントを持っていません。私は返信を受けましたが、私はまだ混乱していて、そのスレッドでは続行できません。Javaストアから未知の長さのバイト配列を取得する

私は以前の会話へのリンクとともに質問を再度投稿しています。

Returning char array from java to string - JNI

私はJavaで保管していたデータは、シリアル化されます。次のコードを使用してJava関数呼び出しを行います。

次のコードは、Javaのcharが2バイトでCのcharが1バイトであるため、CのcharがJavaのbyteと互換性があると仮定しています。 jbyteもsigned char型である*

//value will be the serialized data 
void store(char* key, char* value, int val_len) 

{

//consider the jclass and methodid are already initialized 

    jstring j_key = (*env)->NewStringUTF(env, key); 
    jbyteArray j_value = (*env)->NewByteArray(env, val_len); 

    (*env)->SetByteArrayRegion(env, j_value, 0, val_len, (jbyte *)value); 

    //The store method on java side will save the value (as is) in memory 
    (*env)->CallStaticVoidMethod(j_class, store_method, key, value); 

    (*env)->ReleaseByteArrayElements(env, j_value, (jbyte *)value, JNI_ABORT); 
    (*env)->ReleaseStringUTFChars(env, j_key, key); 

}

Iは、データを保存した後、私はストアからデータを取得するために別の関数を使用します。その時点で私は取得しようとしているデータのサイズを知りません。私のAPIはC言語で、ストアはJavaで書かれています。 C関数を使ってJavaとやり取りします。また、Javaストアから同時にデータを取得する複数のスレッドが存在する可能性があります。

私はCからJavaへの呼び出しを行っています。データを取得した後、コントロールはCプログラムに戻ります。コードがどのように機能するか少し混乱しています。どのように配列(javaから取得)へのポインタを取得し、GetByteArrayElementsを使用してそれを取得するのですか?覚えておいてください私は手の前に取得するため、NewByteArray関数を使用してバイト配列を作成することはできませんし、後でJavaコードのデータでそれを埋めることができないデータのサイズを知っています。

答えて

12

わかりました。他の人もそれを利用できるように、私はここに置くでしょう。

がバイト配列(単にダミーコード、ノーチェックなど)

public static byte[] GetData(){ 
    return myStore.getData(); 
} 

とC側を返し、次のJavaメソッドを考慮し、あなたが

void get_data() 
{  
    int len = 0; 
    char* value = NULL; 
    /*Consider j_class, and j_methodid are already initialized*/ 
    jbyteArray j_value = (*env)->CallStaticObjectMethod(env, j_class, j_methodid); 

    if(j_value != NULL) 
    { 
     len = (*env)->GetArrayLength(env, j_value); 
     value = (*env)->GetByteArrayElements(env, j_value, NULL); 
    } 

    /*later on release the resource*/ 
    (*env)->ReleaseByteArrayElements(env, j_value, value, 0); 
} 
を以下のようにバイト[]を取得することができ

私はそれをチェックして動作します。今私は2次元配列を調べるつもりです。私はあなたがjobjectArrayを取得しているだけで、この配列のすべての要素がjbyteArrayであることと同じであると思います。

+0

ありがとう私は全く同じ問題を抱えており、このコードは役に立ちました。 VisualStudioでは、コンパイルするためにいくつかのキャストを含める必要がありました。(jbyteArray)を使用してCallStaticObjectMethodから戻り値をキャストしなければならず、GetByteArrayElementsの戻り値を(char *)でキャストしなければなりませんでした。 –

+0

ありがとうございます! 4年後、同じ問題がenv->メソッドで発生し、バイト配列フ​​ィールドでの読み込みができなくなりました。この解決策は働いた:) – blkhatpersian

1

ありがとうございました!私はCからJavaへのdouble配列を渡そうとしていました。そして、javaはCに更新されたdouble配列を返します。これはJavaコードをFortranソースコードにリンクしようとしているJNIの一部です。しかし、Fortranのコードは、計算のためにもう1つのJavaコードを呼び出さなければなりません。だから、私はJNIを使​​ってJava to C to Fortran to C to Javaをやっています。 CからJavaへ二重配列を送信する解決策と二重配列をCに戻すJavaはここにあります。

jdoubleArray tempA = (jdoubleArray)(*envG)->NewDoubleArray(envG,3); //create an array with 3 elements to be sent to Java 
jdoubleArray tempB = (jdoubleArray)(*envG)->NewDoubleArray(envG,3); //This is will be //assigned to returned java double array 
(*envG)->SetDoubleArrayRegion(envG,tempA,0,3,(const jdouble *)arr);//need to send the //tempA array to Java. "arr" is the double array coming to C from Fortran! 
int leng = 0; 
for (i = 0; i < 1; i++) { 
//sending an array "tempA" to Java. Java returns tempB, a double array 
tempB = (*envG)->CallObjectMethod(envG, obj_print, id_print,(*A),(*B),(*C),tempA); 
    if (tempB != NULL){ 
    for (k = 0; k < 3; k++){ 
     leng = (*envG)->GetArrayLength(envG, tempB); 
    jdouble* value = (*envG)->GetDoubleArrayElements(envG, tempB, NULL); 
     printf("FROM JAVA ARRAY %f\n", value[k]); 
    } //end for 
    } //end if 
+0

ありがとう。それが他人を助けることを願って – ata

関連する問題