通过JNI接口共享输出流

时间:2009-09-16 20:07:01

标签: java c++ java-native-interface iostream outputstream

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

假设库具有输出功能

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

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

3 个答案:

答案 0 :(得分:6)

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

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

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

鉴于完全自由的选择,没有JNI,但对我而言,它通过使其他不兼容的系统紧密集成而节省了一天。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

  

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

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

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

  

有没有办法强迫   OutputStream到std :: ostream中   JNI层?

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);

你可以做出类似的工作......在美好的一天伴随着风。

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