【问题标题】:Passing large buffers from C++ to Java on Android在 Android 上将大型缓冲区从 C++ 传递到 Java
【发布时间】:2022-06-14 13:57:46
【问题描述】:

我正在尝试找出将大量 (20Kb - 2MB) 数据从 C++ 传递到 Android 上的 Java 的最佳方法。我正在使用Djinni 生成尽可能多的桥接代码。我正在考虑的选项是:

  1. 使用AHardwareBuffer - 看起来像是共享内存的抽象,主要用于 EGL 图像和其他 GLES/Vulkan 渲染需求,但可以在这里使用。因为这里没有与硬件接口,所以我对这里的“硬件”这个词感到不安。也许“硬件”只是意味着该内存可以安全地映射到设备,而我的用例可以吗?此解决方案需要手动编写一些 JNI 代码。

  2. 让 Java 提供缓冲区 - 如果 java 通过 C++ bytes[] 不会复制数据,只会复制数组的地址。这很笨拙,因为 Java 在分配缓冲区之前必须先询问 C++ 缓冲区应该有多大。该解决方案可以使用自动生成的 JNI 代码。

  3. 使用NewDirectByteBuffer / java.nio.ByteBuffer.allocateDirect - Sources,没有引用,声称这是一个糟糕的选择,因为它难以管理并且对于少量数据表现不佳。这就是Google recommends。此解决方案需要手动编写一些 JNI 代码。

我倾向于选项 #2,因为它不需要手写任何 JNI 代码并且看起来“足够好”。我还假设这种方法可以反过来很好地工作(即从 Java 到 C++ 的缓冲区没有/低开销共享)。希望在原型设计/基准测试之前得到你们所有人的想法,因为这样做将是一项相当大的投资。

【问题讨论】:

  • 为什么不只是一个字节数组?为什么要把事情复杂化?您不需要将数组从 Java 传递给 C,只需让 C 创建数组。担心单个 memcopy 确实是过早的优化。
  • 我必须同意@GabeSechan:保持简单并使用byte 数组。 public native byte [] getDataFromNativeCode(...); 只有 分析你的代码证明将数据复制到Java byte[] 是一个瓶颈,你才让它变得更复杂。你猜怎么着?您的“改进”代码很有可能不会更快。见stackoverflow.com/questions/26603285/…
  • 我不担心执行 memcpy 所需的 CPU 周期,我担心额外的内存使用。基于这些回应,我稍微放宽了我的方法。但是,我一直在阅读 JNI 规范,并且正在努力寻找可以保证复制(或不复制)的类型。

标签: java android c++ java-native-interface djinni


【解决方案1】:

Snap 的 Djinni 内置支持传递具有和不具有所有权语义的大型缓冲区。查看此链接了解详情:

https://github.com/Snapchat/djinni#exposing-data-across-language-boundary-with-dataview

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-07
    • 2019-12-13
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 2013-06-14
    相关资源
    最近更新 更多