Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing output streams through a JNI interface

I am writing a Java application that uses a C++ library through a JNI interface. The C++ library creates objects of type Foo, which are duly passed up through JNI to Java.

Suppose the library has an output function

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

and I have a Java OutputStream out. How can I invoke Foo::print from Java so that the output appears on out? Is there any way to coerce the OutputStream to a std::ostream in the JNI layer? Can I capture the output in a buffer the JNI layer and then copy it into out?

like image 802
Chris Conway Avatar asked Sep 16 '09 20:09

Chris Conway


2 Answers

I would implement a C++ ostream that buffers writes (Up to some set size) before flushing those writes to a java OutputStream via JNI.

On the java side, you can either use a regular OutputStream instance, or you can implement queueing of the buffer blocks (essentially byte[]) to avoid any possible locking contention between threads. The real output stream is used only by a task on another thread that pulls blocks from the queue and writes them to the OutpuStream. I can't say if this is necessary or not at this level of detail - you may well find writing directly to the output stream from JNI works.

I don't share the other posters concerns with JNI, and don't see any problem with using JNI for this. Sure, your maintainers will have to know their stuff, but that's about it, and the complexity of the Java/C++ layer can be managed with documentation, examples and test cases. In the past, I've implemented a Java<>COM bridge with quite a chatty interface - no problem with performance, threading or maintainance.

Given a totally free choice, there'd be no JNI, but for me, it has saved the day by making possible the tight integration of otherwise incompatible systems.

like image 71
mdma Avatar answered Sep 18 '22 19:09

mdma


I've posted a writeup on my blog detailing my recent experience with this very same problem. In general, you want to avoid trying to connect an input or output stream to a client in any language as it implies threads. You can incrementally deliver the data using callbacks.

like image 20
Cliff Avatar answered Sep 18 '22 19:09

Cliff