我写的是通过JNI接口采用C ++库的Java应用程序。 C ++库创建类型的对象Foo
,其被正式通过JNI向上传递到Java。
假设图书馆有一个输出功能
void Foo::print(std::ostream &os)
我有一个Java OutputStream out
。 我怎样才能调用Foo::print
从Java使输出出现在out
? 有什么办法要挟OutputStream
到std::ostream
在JNI层? 我可以捕捉在缓冲区中JNI层的输出,然后将其复制到out
?
我将通过JNI冲洗这些写入到Java的OutputStream之前实现C ++的ostream该缓存写入(最多某些集的大小)。
在Java端,既可以使用一个普通的OutputStream实例,也可以执行缓冲块的队列(基本上字节]),以避免线程之间的任何可能的锁定争用。 真正的输出流仅通过对从队列中拉块,并将其写入到OutpuStream另一个线程任务使用。 我不能说,如果这是必要或没有在这个级别的细节 - 你可能会发现直接写入到输出流从JNI工作。
我不同意用JNI其他海报的担忧,并没有看到任何问题与使用JNI这一点。 当然,你的维护者必须知道自己的东西,但仅此而已,而在Java / C ++层的复杂性可与文档,示例和测试案例进行管理。 在过去,我实现了一个Java <> COM桥相当繁琐的界面 - 与性能,螺纹或修的没有问题。
给定一个完全自由的选择,那么便没有如此JNI,但对我来说,这已经使得可能不兼容的系统的紧密集成化险为夷。
我已经发布了一个在我的博客的书面记录 ,详细说明与此同样的问题,我最近的经验。 在一般情况下,要避免试图输入或输出流连接到客户端在任何语言,因为这意味着线程。 您可以使用回调逐步交付的数据。
我怎样才能调用美孚::打印从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中重新编码的东西。