0

Javaとネイティブ部分を持つAndroidアプリケーションを書いています。Java 部分はネイティブ部分にメッセージを送信し、応答を受け取ります。ネイティブ部分はすべて別のスレッドで動作し、回答が返されたらメイン スレッドで回答を処理したいと考えています。これが私の拡張 Application クラスの一部です。

@Override
public void OnMessage(final Message msg, final long answerTo) {
    Log.i(TAG, msg.ToStr()); // OK
    handler.post(new Runnable() {
        @Override
        public void run() {
            Log.i(TAG, msg.ToStr()); // Fatal signal 11 (SIGSEGV)
                                     // at 0x74616862 (code=1), thread 13255
        }
    });
}

ネイティブ コードは、そのスレッドで OnMessage メソッドを呼び出し、それを Handler を介して UI スレッドに渡そうとします。また、UI スレッド内で msg のメソッドを使用しようとすると、プログラムが SEGSEGV で失敗します。

重要な事実は、Message クラスが C++ Message クラスのラッパーであることです。ラッパーはSWIGによって生成されました。

GDB でデバッグしようとしましたが、GDB はネイティブの Message.toStr メソッドで終了するスタック トレースも表示します。しかし、gdb は変数の出力を拒否し、「現在のコンテキストには記号 " * " がありません」と言っています。

この問題を解決するのを手伝ってください。

4

2 に答える 2

0

あなたがやろうとしていること(スレッド間でオブジェクトをコピーする)に対して適切に Handler を使用しているとは思いません。ここのブログ投稿をチェックしてください:

http://techtej.blogspot.com/2011/02/android-passing-data-between-main.html

具体的には、次のようなハンドラーへのメッセージの送信:

Message msg = Message.obtain();
msg.obj =  // Some Arbitrary object
mHandler.sendMessage(msg);

Runnable を実行しているだけなので、スレッド間のデータ コピーの Handler マジックを実行する方法ではないと思います。

編集: これが問題だったのか知りたいので、そうでなくてもコメントで返信して結果を教えてもらえますか?

編集 2: したがって、オブジェクトはおそらく JNI レイヤーにローカル ref として格納されているようです。残念ながら、それはあなたの目的には十分ではありません。グローバル参照にする必要があるかもしれません。グローバル参照にする場合は、使い終わったときにネイティブコードで自分で削除する必要があることに注意してください。

http://developer.android.com/training/articles/perf-jni.html#local_and_global_references

于 2013-08-08T23:45:37.397 に答える
0

最後に、私は自分で問題を解決しました。問題は、C++ から Java への呼び出しを行うときに、SWIG プロキシ メソッドがその引数へのポインタを Java 側に渡すことでした。何かのようなもの:

void SwigDirector_NativeLayerDelegate::OnMessage(Message msg, Long answer_to) {
  ...
  *((Message **)&jmsg) = &msg;
  ...
  jenv->CallStaticVoidMethod(..., jmsg, ...);
  ...
}

Java 側では、別のプロキシ メソッドがポインタを受け取り、それを Message クラスの Java 表現でラップして、Java メソッド OnMessage に渡しました。

  public static void SwigDirector_NativeLayerDelegate_OnMessage(
     NativeLayerDelegate self, long msg, long answer_to) {
    self.OnMessage(new Message(msg, false), answer_to);
    // false parameter means that Message object isn't owner of 'msg' pointer, so it
    // shouldn't free it on finalize.
  }

OnMessage の終了後、ネイティブ Message オブジェクトは破棄されSwigDirector_NativeLayerDelegate::OnMessage、Java Message オブジェクトは破棄されたネイティブ オブジェクトへのポインタを保持していました。

解決

Message オブジェクトのカスタム タイプマップを作成しました。

%typemap(directorin,descriptor="L$packagepath/$javaclassname;") Message
  %{*((Message**)&$input) = new Message($1);%}
%typemap(javadirectorin,descriptor="L$packagepath/$javaclassname;") Message
  %{new Message($1, true)%}

SwigDirector_NativeLayerDelegate::OnMessage が のコピーを作成しmsg、Java オブジェクトがそれを所有するようになりました。

// Native
void SwigDirector_NativeLayerDelegate::OnMessage(Message msg, Long answer_to) {
  ...
  *((Message**)&jmsg) = new Message(msg);
  ...
  jenv->CallStaticVoidMethod(..., jmsg, ...);
  ...
}

// Java
public static void SwigDirector_NativeLayerDelegate_OnMessage(
     NativeLayerDelegate self, long msg, long answer_to) {
    self.OnMessage(new Message(msg, true), answer_to);
}
于 2013-08-11T01:14:58.393 に答える