2009-09-16 7 views
12

Ich schreibe eine Java-Anwendung, die eine C++ - Bibliothek über eine JNI-Schnittstelle verwendet. Die C++ - Bibliothek erstellt Objekte vom Typ Foo, die ordnungsgemäß über JNI an Java übergeben werden.Gemeinsame Nutzung von Ausgabeströmen über eine JNI-Schnittstelle

Angenommen, die Bibliothek eine Ausgabefunktion

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

hat, und ich habe eine Java OutputStream out. Wie kann ich Foo::print von Java aufrufen, so dass die Ausgabe auf out erscheint? Gibt es eine Möglichkeit, die OutputStream zu einer std::ostream in der JNI-Schicht zu zwingen? Kann ich die Ausgabe in einem Puffer die JNI-Schicht erfassen und dann in out kopieren?

Antwort

0

Wie kann ich Foo :: print von Java aufrufen, so dass die Ausgabe auf out?

Konzeptionell, die Art und Weise Foo :: print (...) zu einer vorhandenen Java Output Instanz schreiben zu erhalten, ist eine C++ std :: ostream Implementierung zu schreiben, die tatsächlich einen Rückruf in Java tut Ausgabe zu tun .

Das klingt möglich, aber ich möchte den Code nicht schreiben/pflegen. Zur Laufzeit haben Sie Anrufe von Java -> C++ -> Java, und es gibt viele Möglichkeiten, Fehler zu machen, die Ihre JVM zufällig zum Absturz bringen.

Gibt es eine Möglichkeit, den Output zu einem std :: ostream in der JNI Schicht zu zwingen?

AFAIK-Nr.

Kann ich die Ausgabe in einem Puffer die JNI-Schicht erfassen und kopieren Sie sie dann in aus?

Meinst du etwas in etwa so?

Sie können wahrscheinlich so etwas machen ... an einem guten Tag mit einem folgenden Wind.

Aber ich denke, dass Sie wirklich anstreben sollten, den C++ Code zu beseitigen, anstatt zu versuchen, immer kompliziertere Sachen über JNI zu machen. IMO, JNI sollte nur als letzter Ausweg und nicht als Abkürzung verwendet werden, um das Umcodieren von Daten in Java zu vermeiden.

+0

Eine Neuimplementierung der Bibliothek in Java ist keine Option (sie ist groß, ausgereift und leistungsintensiv). –

+0

Vielleicht sollten Sie dann nicht versuchen, es von Java aus aufzurufen. Mein Punkt ist, dass Sie wahrscheinlich eine Menge Schmerz für sich selbst und für Leute erzeugen, die Ihren Code pflegen müssen. –

+2

Während ich zustimme, JNI-Code ist schwierig zu sagen, man sollte es vermeiden, es ist nicht fair. Es gibt definitiv einen Ort für JNI, speziell mit großen Legacy-Projekten wie den erwähnten und in meinem Fall 3rd Party APIs, die Sie verwenden müssen, um die Arbeit zu erledigen. Das ist eine sehr gültige Frage, nach der ich auch eine Antwort suche. – Cliff

1

Ich habe eine writeup on my blog detailliert meine jüngsten Erfahrungen mit diesem Problem beschrieben. Im Allgemeinen möchten Sie vermeiden, dass Sie versuchen, einen Eingabe- oder Ausgabestream mit einem Client in einer beliebigen Sprache zu verbinden, da dies Threads beinhaltet. Sie können die Daten schrittweise mithilfe von Rückrufen bereitstellen.

6

Ich würde ein C++ - Ostream implementieren, der Schreibvorgänge puffert (bis zu einer bestimmten Größe), bevor diese Schreibvorgänge über JNI in einen Java-OutputStream übertragen werden. Auf der Java-Seite können Sie entweder eine reguläre OutputStream-Instanz verwenden, oder Sie können die Warteschlangenbildung der Pufferblöcke implementieren (im Wesentlichen byte []), um mögliche Sperrkonflikte zwischen Threads zu vermeiden. Der tatsächliche Ausgabestream wird nur von einer Task in einem anderen Thread verwendet, der Blöcke aus der Warteschlange abruft und sie in den OutpuStream schreibt.Ich kann nicht sagen, ob dies auf dieser Detailebene notwendig ist oder nicht - Sie können das Schreiben direkt in den Ausgabestrom von JNI finden.

Ich teile nicht die anderen Plakate Anliegen mit JNI, und sehe kein Problem mit der Verwendung von JNI für diese. Sicher, Ihre Betreuer müssen ihre Sachen kennen, aber das ist es auch schon, und die Komplexität der Java/C++ - Ebene kann mit Dokumentation, Beispielen und Testfällen verwaltet werden. In der Vergangenheit habe ich eine Java <> COM-Bridge mit einer ziemlich gesprächigen Schnittstelle implementiert - kein Problem mit Performance, Threading oder Wartung.

Angesichts einer völlig freien Wahl würde es kein JNI geben, aber für mich hat es den Tag gerettet, indem es die enge Integration von ansonsten inkompatiblen Systemen ermöglicht hat.

+0

Bonuspunkte für das Nicht-Jammern auf JNI. – rdb

Verwandte Themen