2011-07-19 10 views
3

私は、Cとの統合が必要なx86用のAndroidアプリで作業しています。私はswig/JNIを使​​ってこのトリックを行いました。部。しかし、ポインタは私にいくつかのエラーを与えてきました。CからJavaへのポインタを渡すとNULLになる

私の問題は、エミュレータ(ARM)では変数のアドレスを正常に参照できますが、デバイス(x86)では問題ありません。

this linkの例を使って、このアドレスがJavaに渡されると、Cの割り当て済み変数のアドレスはNULLになることがわかりました。たとえば...

ガブガブ飲む-生成JNI:new_intpを含む

SWIGEXPORT jlong JNICALL Java_exampleJNI_new_1intp(JNIEnv *jenv, jclass jcls) { 
    jlong jresult = 0 ; 
    int *result = 0 ; 
    (void)jenv; 
    (void)jcls; 
    result = (int *)new_intp(); 
    LOGI("Result is %x", result); 
    *(int **)&jresult = result; 
    LOGI("JResult is %x", jresult); 
    return jresult; 
} 

ソースファイル():

static int *new_intp() { 
    return (int *) calloc(1,sizeof(int)); 
} 

私はアドレスの値をチェックするprint文を持っていますそれはCで始まり、Javaに渡されます。 new_intp()では、新しい変数には見栄えの良いアドレスが割り当てられますが、この値がJNIに戻ってjlong​​としてキャストされるとNULLに変わります。言い換えれば

*(int **)&jresult = result;原因は0

このエラーが発生する理由であることをjresult? JNIがポインタで動作することを禁止するx86の特殊性はありますか?それとも、エミュレータではなく物理的なデバイスでテストしているからですか?

ありがとうございます。

+1

「これは」と呼ばなければなりませんか?これは、JavaとC++の両方で予約されているキーワードです。 –

+0

Cではそうではありません。それはおそらく、名前を持つ変数を与えることを最善の習慣ではありません。それを編集するつもり。 – digitalmouse12

+0

ああ、申し訳ありませんが、私はあなたの質問のタイトルで混乱しました。これはCかC++の質問ですか、適切にタグを付けることができますか? –

答えて

2

それはエンディアン問題である可能性がありますように私に見えます。

*(int **)&jresult = result; 

intが32ビットであり、そしてjresultが64ビットである場合には、ビッグエンディアンアーキテクチャ上で、これは予期しない結果を与えることができます。

&jresultは64ビット値へのポインタなので、32ビット値へのポインタにキャストすると、2つの32ビット構成ワードのうちの下位アドレスを指しています。ビッグ・エンディアン・システムでは、これが最も重要な単語になります。したがって、32ビットワードを64ビット値の最も重要な末尾に書き込んだ後、64ビット値は2^32倍になります。

あなたLOGI呼び出しが32ビットのintとしてパラメータを処理すると、暗黙的にダウンキャストを64ビットの値からされている場合、これは代わりに動作するかどうか、あなたが見ることができる0

を与えるのだろうか?

jresult = (jlong) result; 
+0

うわー!それはうまくいくようですが、私はx86がリトルエンディアンだと思いました。 – digitalmouse12

+0

@ digitalmouse12おそらく、システムのいくつかの部分はリトルエンディアンになっているはずなのに - x86のアンドロイドは公式ではないことを忘れないでください。メモリからバイト単位でjresult(ターゲットではなくポインタ)の生の値をダンプし、直接代入の場合とポインタハッカーの場合の違いがあるかどうかを確認してください。 32ビットデスクトップLinuxでこれを行うと、違いはありませんが、ターゲットシステムではありません。 –

+1

@Graham Borland:実際これは[ポインタエイリアシング](http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule)の問題です。 – paleozogt

10

実際には、これはpointer-aliasingです。 SWIGは、旧式のCポインタ技術を使用しています。これは、最適化がオンのときに新しいGCCで動作しません。あなたが最適化を使用しようとしている場合(たとえば-O2用)のgcc でオン

重要

、あなたはまた、-fno-厳格でコンパイルすることを確認:それは、具体的says what to do SWIGのドキュメントに埋葬 - アリアシング。 GCCの最適化はgcc-4.0以降では より積極的になり、厳密なエイリアスの最適化で失敗したコードになります がオンになります。詳細については、C/C++ to Java typemapsセクションを参照してください。

関連する問題