2009-09-16 16 views
12

JNIインターフェイスを介してC++ライブラリを使用するJavaアプリケーションを作成しています。 C++ライブラリは、タイプFooのオブジェクトを作成します。これらのオブジェクトは、JNIからJavaに正式に渡されます。JNIインターフェイスを介した出力ストリームの共有

は、ライブラリが

void Foo::print(std::ostream &os) 

出力機能を持っていると私はJavaのOutputStream outがあるとします。 JavaからFoo::printを呼び出して、出力がoutに表示されるようにするにはどうすればよいですか? OutputStreamをJNIレイヤーのstd::ostreamに強制する方法はありますか? JNIレイヤのバッファに出力をキャプチャしてoutにコピーできますか?

答えて

0

からFoo :: printを呼び出して、出力が表示されるようにするにはどうすればよいですか?

概念的には、話して、既存のJavaのOutputStreamインスタンスへの書き込みにはFoo ::プリント(...)を取得する方法は、実際に出力を行うためにJavaへのコールバックを行うC++のstd :: ostreamに実装を書くことです。

それは可能ですが、私はコードを書いたり維持したりしたくありません。実行時にはJava - > C++ - > Javaからの呼び出しがあり、JVMがランダムにクラッシュする間違いを犯す機会がたくさんあります。

STDへ OutputStreamを強制する方法はあります:: JNI層中のostream?

AFAIK no。

は、私は、バッファ JNI層での出力をキャプチャし うちにそれをコピーできますか?

これはおおよそ次のような意味ですか?

MyJNIThing m = ... 
    int myOstream = m.createMemoryBackedOStream(...); // native method 
    ... 
    m.someMethodWrapper(... myOStream); // native method 
    ... 
    byte[] data = m.getCapturedData(myOStream); // native method 
    out.write(data); 

あなたはおそらく、次の風との良好な日に...その仕事のようなものを作ることができます。

しかし、JNI全体でますます複雑化することをやろうとするのではなく、C++コードを排除することを本当に目指すべきだと思います。 IMO、JNIは最後の手段として使用するだけで、Javaでのコードの再作成を避けるための短期間ではありません。

+0

Javaでのライブラリの再実装はオプションではありません(大規模で成熟し、パフォーマンスが向上します)。 –

+0

おそらく、あなたはJavaからそれを呼び出すべきではないでしょう。私の主張は、あなた自身とあなたのコードを維持しなければならない人々のために多くの痛みを引き起こす可能性が高いということです。 –

+2

私はJNIコードには間違いを避けるべきだと言うのは難しいと同意しているが、それは公正ではない。間違いなく、JNIのための場所は、特にopのような大規模なレガシープロジェクトと私の場合は、仕事を完了するために使用する必要がありますサードパーティ製のAPIです。これは非常に有効な質問です。私も同様の答えを探しています。 – Cliff

1

この非常に同じ問題で私の最近の経験を詳述したwriteup on my blogを投稿しました。一般に、入力ストリームまたは出力ストリームをクライアントに接続するのは、スレッドを意味するため、どの言語であってもかまいません。コールバックを使用してデータを段階的に配信することができます。

6

JNI経由でJava OutputStreamへの書き込みをフラッシュする前に、書き込みをバッファリングするC++ ostreamを実装します。

Java側では、通常のOutputStreamインスタンスを使用するか、バッファブロックのキューイング(本質的にはbyte [])を実装してスレッド間のロック競合を回避できます。実際の出力ストリームは、キューからブロックを引き出し、それらをOutpuStreamに書き込む別のスレッドのタスクによってのみ使用されます。この詳細レベルでこれが必要かどうかは言えません.JNIの作品の出力ストリームに直接書くことができます。

私は他のポスターの懸念事項をJNIと共有していません。このためにJNIを使​​用する際に問題はありません。確かに、保守担当者は自分のことを知る必要がありますが、それはそれで、Java/C++レイヤーの複雑さはドキュメント、サンプル、テストケースで管理できます。これまでは、Javaのコードを実装しました。パフォーマンス、スレッド化、メンテナンスに問題はありません。

完全に自由な選択であれば、JNIはありませんが、私にとっては、それ以外の互換性のないシステムとの緊密な統合を可能にすることで、その日を救っています。

+0

JNIにバッシングしないためのボーナスポイント。 – rdb

関連する問題