2011-06-23 16 views
5

私はこの問題のほとんどをこのタイトルのタイトルに当てはめることができました。JNI - 基本Javaオブジェクト(ブール値)を表すjobjectをネイティブの基本型(ブール値)に変換する

私はネイティブC++コードで、Javaからオブジェクトを引き戻すことだ:

jobject valueObject = env->CallObjectMethod(hashMapObject, hashMapGetMID, keyObject); 

私は戻りオブジェクト天気をチェックすることが可能だがのようなものを使用してネイティブ型のいずれかです。

jclass boolClass = env->FindClass("java/lang/Boolean"); 
if(env->IsInstanceOf(valueObject, boolClass) == JNI_TRUE) { } 

これで、私はブール値であることを知っているjobjectを持っています(大文字のBに注意してください)。質問は、これを(これは私のネイティブコードでjobjectを持っていると考えています) a bool。タイプキャスティングは意味をなさない。

上記の例はブール値ですが、Character-> char、Short-> short、Integer-> int、Float-> float、Double-> doubleも変換したいと考えています。

(私はそれを実装した後、私はBoolean.booleanValue()を行い、この答えを掲載する予定)

+0

Javaコードで型キャストとアンボックスを処理するだけではどうですか? –

答えて

5

2つの選択肢があります。

オプション#1はあなた自身の答えに書いたものです。各クラスに定義されたパブリックメソッドを使用してプリミティブ値を抽出します。

オプション#2は高速ですが、厳密には法的ではありません。内部フィールドに直接アクセスしてください。 Booleanの場合、Boolean.valueになります。各プリミティブボックスクラスに対して、 "value"フィールドのfieldIDがあり、フィールドを直接読むだけです。 (JNIは、それが私的に宣言されているという事実を無視しています。また、「最終的な」フィールドに書き込んで、「本当に悪いアイデア」カテゴリに入るその他のものも実行できます)。それはシリアル化を中断するので変更してください。だから公式にはこれはお勧めしませんが、実際には必要な場合にはそれを取り除くことができます。

どちらの方法でも、jmethodID/jfieldIDの値をキャッシュして、毎回ルックアップしないでください(ルックアップが比較的高価です)。

ボックスクラスが「最終」であるため、IsInstanceofよりも安価なIsSameObject関数を使用することもできます。そのためには、valueObjectのクラスを取得するために余分なGetObjectClassを呼び出す必要がありますが、これはさまざまな比較の前に一度行う必要があります。

ところで、 "char"の使用には注意してください。上記の例では、CallCharMethod(16ビットUTF-16値)の結果をchar(8ビット値)にキャストしています。覚えて、char!= jchar(ワイド文字用に設定されていない限り)、long!= jlong​​(64ビット長でコンパイルしない限り)。

+0

すばらしい答えありがとう!便利な情報がたくさんありますが、わかりません。特定のリソースが推奨されていますか、試してみた「血、汗、涙」のアプローチですか? :) – Graeme

+2

あなたがここで求めていることの種類は、おそらく本から学ぶことはできません。あなた自身のVMを書く時間があれば、確かに多くのことを学ぶでしょう。それがなければ、たくさんのコードを書いて、それがなぜ壊れているのか理解しようとします。 :-) – fadden

1

これは私がこれ以上の入力を取得する場合に使用するつもりだソリューションです。うまくいけば、それはこの難しいことではありませんが、私はそれがあるかもしれないと思っていJNIを知る:一般的に

if  (env->IsInstanceOf(valueObject, boolClass)   == JNI_TRUE) 
    { 
     jmethodID booleanValueMID = env->GetMethodID(boolClass, "booleanValue", "()Z"); 
     bool booleanValue   = (bool) env->CallBooleanMethod(valueObject, booleanValueMID); 
     addBoolean(key, booleanValue); 
    } 
    else if(env->IsInstanceOf(valueObject, charClass)   == JNI_TRUE) 
    { 
     jmethodID characterValueMID = env->GetMethodID(charClass, "charValue", "()C"); 
     char characterValue   = (char) env->CallCharMethod(valueObject, characterValueMID); 
     addChar (key, characterValue); 
    } 
0

、私は、パフォーマンスの向上のためにJNIを書きます。 より良いパフォーマンスを得るには? asmを使用して、プリミティブ型といくつかのメソッド呼び出し。私は

など、あなたのメソッドの戻り値の型が、このような JINTとき、jlong​​とき、jboolean、jbyteとjcharとして、C/C++で使用できるが、設計冗長関数呼び出しを示唆して変換 は非効率的とunmaintainable実装を行います。

+0

パフォーマンスよりもダイナミックなコードを使用しています。実行時の値はどのような基本型でもかまいません。そのため、JNIを使​​って型をチェックしたり呼び出すことなく、jobjectをbool/char/intなどに変換する最も良い方法を見つけようとしています。 – Graeme

+0

Javaレベルでダイナミックで柔軟性がある方が良いです。私はそう思う。 – qrtt1

+0

私も!しかし、私はロジックの特定の部分が実行される場所を選択する必要はありません。 – Graeme

関連する問題