使用SWIG实现Java侧访问C++返回的uint8_t类型std::vector数据
实现方案
方案1:返回Direct ByteBuffer(优先,零拷贝性能更高)
你只需要在SWIG的接口配置文件(.i后缀)中添加针对std::vector<uint8_t>返回值的自定义类型映射,即可自动调用JNI的NewDirectByteBuffer方法:
%include "std_vector.i" // 为std::vector<uint8_t>配置返回ByteBuffer的类型映射 %typemap(out) std::vector<uint8_t> { // 调用JNI NewDirectByteBuffer,传入数据指针和长度 $result = jenv->NewDirectByteBuffer($1.data(), $1.size()); } // 声明你要导出的C++类 %include "ArduGrabClass.h"
- 上述配置默认不会主动释放C侧的内存,完全符合你C持有buffer后续自主释放的需求
- 如果你想要彻底避免
std::vector的内存拷贝,可以直接修改C++方法返回原始BUFFER*指针,再针对BUFFER*写类型映射,直接取buffer->data和buffer->length创建ByteBuffer,实现完全零拷贝
方案2:返回字节数组(备选)
如果需要返回byte[]类型,替换为如下类型映射即可:
%include "std_vector.i" %typemap(out) std::vector<uint8_t> { // 创建对应长度的Java字节数组 $result = jenv->NewByteArray($1.size()); // 把C++侧的数据拷贝到Java数组 jenv->SetByteArrayRegion($result, 0, $1.size(), (const jbyte*)$1.data()); }
字节数组方案会触发一次全量内存拷贝,数据量大时性能低于Direct ByteBuffer方案
你只需要把C++类中用于释放buffer的方法正常声明在SWIG接口文件中,就可以在Java侧调用该方法完成内存释放,不需要额外特殊配置。
内容的提问来源于stack exchange,提问作者Neil Benn
相关产品推荐
相关产品推荐

