通过JNI接口共享输出流

我正在编写一个通过JNI接口使用C ++库的Java应用程序。 C ++库创建了Foo类型的对象,它们通过JNI传递给Java。

假设库具有输出function

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

我有一个Java OutputStream out 。 如何从Java调用Foo::print以使输出显示out ? 有没有办法将OutputStream强制转换为JNI层中的std::ostream ? 我可以在缓冲区中捕获JNI层的输出,然后将其复制到out吗?

我会实现一个C ++ ostream来缓冲写入(最多一些设置大小),然后通过JNI将这些写入刷新到java OutputStream。

在java方面,您既可以使用常规的OutputStream实例,也可以实现缓冲区块的排队(实际上是byte []),以避免线程之间发生任何可能的锁定争用。 实际输出流仅由另一个线程上的任务使用,该线程从队列中提取块并将它们写入OutpuStream。 我不能说在这个细节层次上是否有必要 – 你可能会发现直接写入JNI工作的输出流。

我不与JNI分享其他海报问题,也没有看到使用JNI的任何问题。 当然,你的维护者必须知道他们的东西,但就是这样,Java / C ++层的复杂性可以通过文档,示例和测试用例来管理。 在过去,我已经实现了一个Java <> COM桥接器,其界面非常繁琐 – 性能,线程或维护都没有问题。

鉴于完全自由的选择,没有JNI,但对我来说,它通过使其他不兼容系统的紧密集成成为可能来节省时间。

我在我的博客上发布了一篇文章,详细介绍了我最近遇到的同样问题。 通常,您希望避免尝试使用任何语言将输入或输出流连接到客户端,因为它意味着线程。 您可以使用回调递增地传递数据。

如何从Java调用Foo :: print以使输出显示在外?

从概念上讲,让Foo :: print(…)写入现有Java OutputStream实例的方法是编写一个C ++ std :: ostream实现,该实现实际上对Java进行回调以进行输出。

这听起来有可能,但我不想编写/维护代码。 在运行时,您将从Java调用 – > C ++ – > Java,并且有很多机会犯错会随机崩溃您的JVM。

有没有办法将OutputStream强制转换为JNI层中的std :: ostream?

AFAIK没有。

我可以在缓冲区中捕获JNI层的输出,然后将其复制到外面吗?

你的意思是这样的吗?

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

你可以做出像这样的工作……在美好的一天伴随着风。

但我认为你应该真正想要消除C ++代码,而不是试图在JNI上做越来越复杂的事情。 IMO,JNI应该只作为最后的手段,而不是捷径,以避免重新编写Java中的东西。