java - 使用 SWIG 在 Java 和 C++ 之间传递缓冲区
问题描述
我想使用 SWIG 在 Java 和 C++ 之间传递一段信息(例如 1024 字节的内存)。C++中定义的结构如下:
struct Buffer
{
unsigned char *addr;
size_t size;
}
为此,我应该如何编写 SWIG 接口文件?
解决方案
目前还不完全清楚你想要达到什么目的。
如果您想将您的映射Buffer
到 Java byte[]
,您可以使用自定义类型映射:
%typemap(jni) Buffer "jbyteArray"
%typemap(jtype) Buffer "byte[]"
%typemap(jstype) Buffer "byte[]"
%typemap(in) Buffer {
$1.addr = (unsigned char *) JCALL2(GetByteArrayElements, jenv, $input, 0);
$1.size = JCALL1(GetArrayLength, jenv, $input);
}
%typemap(argout) Buffer {
JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *) $1.addr, 0);
}
%typemap(out) Buffer {
$result = JCALL1(NewByteArray, jenv, $1.size);
JCALL4(SetByteArrayRegion, jenv, $result, 0, $1.size, (jbyte *) $1.addr);
delete[] $1.addr;
}
%typemap(javain) Buffer "$javainput"
%typemap(javaout) Buffer { return $jnicall; }
然后像 C++ 代码
Buffer getData();
void sendData(Buffer arg);
将映射到Java:
public static byte[] getData() { ... }
public static void sendData(byte[] arg) { ... }
将数据传递给 Java 的困难在于将其放入 JVM 堆和/或管理数据的生命周期。通过一些复制很容易实现,但真正的 0-copy 解决方案通常需要更改 C++ 接口。
完整示例:
例子.h
#include <stddef.h>
struct Buffer
{
unsigned char *addr;
size_t size;
};
Buffer getData();
void sendData(Buffer);
例子.cxx
#include "example.h"
Buffer getData() {
Buffer rc { new unsigned char[64], 64 };
for (int i = 0; i < rc.size; ++i)
rc.addr[i] = 0x40 + i;
return rc;
}
void sendData(Buffer buf) {
// use buf.addr
}
例子.i
%module example
%{
#include "example.h"
%}
%typemap(jni) Buffer "jbyteArray"
%typemap(jtype) Buffer "byte[]"
%typemap(jstype) Buffer "byte[]"
%typemap(in) Buffer {
$1.addr = (unsigned char *) JCALL2(GetByteArrayElements, jenv, $input, 0);
$1.size = JCALL1(GetArrayLength, jenv, $input);
}
%typemap(argout) Buffer {
JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *) $1.addr, 0);
}
%typemap(out) Buffer {
$result = JCALL1(NewByteArray, jenv, $1.size);
JCALL4(SetByteArrayRegion, jenv, $result, 0, $1.size, (jbyte *) $1.addr);
delete[] $1.addr;
}
%typemap(javain) Buffer "$javainput"
%typemap(javaout) Buffer { return $jnicall; }
%ignore Buffer;
%include "example.h"
测试.java
class test {
public static void main(String[] args) throws Exception {
System.loadLibrary("_example");
byte[] data = example.getData();
System.out.println(new String(data));
}
}
输出:
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂
推荐阅读
- python - Spark 的 MapType 是确定性的,即使用 map_keys/map_values 手动爆炸时键值对是否正确配对?
- state - Apache Flink 中的有状态函数
- c - 在 c 编程语言中联合的实际使用?
- hive - Cloudera 发行版中的 hive-site.xml 在哪里?
- scala - 如何在 Spark 和 Scala 中动态构建模型类
- javascript - Gulp 修复生成文件的导入
- android - 即使我在android登录表单中输入了错误的信用,总是得到响应匹配(200)并登录?
- go - 是否有可能从 err interface Go 获取额外的数据?
- c++ - C++ 代码中的错误:在函数“int main(int, char**)”中:
- django - 分叉 django-oscar 视图显示错误