使用 SWIG 在 Java 和 C++ 之间传递缓冲区 [英] Passing buffer between Java and C++ using SWIG

查看:28
本文介绍了使用 SWIG 在 Java 和 C++ 之间传递缓冲区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 SWIG 在 Java 和 C++ 之间传递一段信息(例如 1024 字节的内存).C++中定义的结构如下:

I want to pass a segment of info (e.g. 1024 bytes of memory) between Java and C++ using SWIG. The structure defined in C++ is as follows:

struct Buffer
{
    unsigned char *addr;
    size_t        size;
}

为此我应该如何编写 SWIG 接口文件?

How should I write the SWIG interface file for that purpose?

推荐答案

并不完全清楚您想要达到的确切目标.

It's not entirely clear what you want to achieve exactly.

如果您想将 Buffer 映射到 Java byte[],您可以使用自定义类型映射:

If you want to map your Buffer to a Java byte[], you can do it with a custom typemap:

%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 复制解决方案通常需要更改 C++ 接口.

The difficulty with passing data to Java is to get it into the JVM heap and/or to manage the lifetime of the data. It's easy to achieve with some copying, but a truly 0-copy solution will often require a change in the C++ interface.

完整示例:

example.h

#include <stddef.h>
struct Buffer
{
    unsigned char *addr;
    size_t        size;
};
Buffer getData();
void sendData(Buffer);

example.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
}

example.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"

test.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{|}~⌂

这篇关于使用 SWIG 在 Java 和 C++ 之间传递缓冲区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆