通过JNI接口共享输出流(Sharing output streams through a JNI

2019-08-07 01:36发布

我写的是通过JNI接口采用C ++库的Java应用程序。 C ++库创建类型的对象Foo ,其被正式通过JNI向上传递到Java。

假设图书馆有一个输出功能

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

我有一个Java OutputStream out 。 我怎样才能调用Foo::print从Java使输出出现在out ? 有什么办法要挟OutputStreamstd::ostream在JNI层? 我可以捕捉在缓冲区中JNI层的输出,然后将其复制到out

Answer 1:

我将通过JNI冲洗这些写入到Java的OutputStream之前实现C ++的ostream该缓存写入(最多某些集的大小)。

在Java端,既可以使用一个普通的OutputStream实例,也可以执行缓冲块的队列(基本上字节]),以避免线程之间的任何可能的锁定争用。 真正的输出流仅通过对从队列中拉块,并将其写入到OutpuStream另一个线程任务使用。 我不能说,如果这是必要或没有在这个级别的细节 - 你可能会发现直接写入到输出流从JNI工作。

我不同意用JNI其他海报的担忧,并没有看到任何问题与使用JNI这一点。 当然,你的维护者必须知道自己的东西,但仅此而已,而在Java / C ++层的复杂性可与文档,示例和测试案例进行管理。 在过去,我实现了一个Java <> COM桥相当繁琐的界面 - 与性能,螺纹或修的没有问题。

给定一个完全自由的选择,那么便没有如此JNI,但对我来说,这已经使得可能不兼容的系统的紧密集成化险为夷。



Answer 2:

我已经发布了一个在我的博客的书面记录 ,详细说明与此同样的问题,我最近的经验。 在一般情况下,要避免试图输入或输出流连接到客户端在任何语言,因为这意味着线程。 您可以使用回调逐步交付的数据。



Answer 3:

我怎样才能调用美孚::打印从Java使输出上出现了呢?

从概念上讲,拿到美孚::打印(...)写入到现有的Java的OutputStream实例的方式是写一个C ++的std :: ostream的实现,实际上做了回调到Java来做输出。

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

有没有办法强迫在JNI层中的OutputStream到一个std :: ostream的?

据我所知没有。

我可以捕捉在缓冲区中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中重新编码的东西。



文章来源: Sharing output streams through a JNI interface