SWIG typemap uint8_t *从C / C ++到java.nio.ByteBuffer

时间:2016-12-23 12:35:37

标签: java c++ swig

我正在尝试将输入和输出缓冲区从C ++传递给java类。 出于效率原因,我需要使用ByteBuffer。

两个缓冲区都是在C ++部分中分配的,我需要将它们传递给一个java函数,该函数将使用输入缓冲区进行一些计算,并将结果写入输出缓冲区。

以下是C ++如何显示的简化示例:

// SWIG mapped with %feature("director") JavaDelegate;
class JavaDelegate {
public:
    JavaDelegate() {}
    virtual ~JavaDelegate() {}
    virtual int compute(const uint8_t* input, size_t inSize,
                        uint8_t* output, size_t maxOutSize,
                        int someFlag) = 0;
};

// assume inputBuf is filled with valid data
std::vector<uint8_t> inputBuf;
std::vector<uint8_t> outputBuf(10000);

// delegate also points to a valid SWIG mapped class
JavaDelegate* delegate;

void computeOutput() {
   int someFlag = 1;
   int numValuesComputed = delegate->compute(inputBuf.data(), inputBuf.size(), 
                                             outputBuf.data(), outputBuf.size(), 
                                             someFlag);
   std::cout << "Computed " << numValuesComputed << " value from input.\n";
}

在Java方面,我希望实现这一点(SWIG已生成JavaDelegate类):

public class Delegate extends JavaDelegate {

    public long compute(java.nio.ByteBuffer input, 
                        java.nio.ByteBuffer output, 
                        long someFlag) 
    {
        // read input
        // compute something n values from m input values
        // write result to output
        return numOutputValues;
    }
}

问题是,我根本无法弄清楚如何将一个普通的char *包装到ByteBuffer中,特别是结合SWIG为抽象基类打开的导演功能。 我知道如何将ByteBuffer从Java传递给C ++,但我不知道如何反过来。

任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:1)

前言:这不是SWIG-ish解决方案,这是通用的,我发现this与您的问题有些相关

首先,据我所知,Java中没有ref参数,因此除非您准备更改签名并将其作为返回值,否则不能直接从C ++传递它。这可以通过从Java传递typewrapper并在其中包含C ++创建/设置缓冲区来避免,la:

public class BufferWrapper {
    private ByteBuffer mBuffer;

    public void setBuffer(ByteBuffer buffer) {
        mBuffer = buffer;
    }
} 

将它传递给C ++并让它分配并设置缓冲区到包装器。

NewDirectByteBuffer JNI函数可以完全满足您的需求:

  

分配并返回指向的直接java.nio.ByteBuffer   从存储器地址开始并扩展的存储器块   容量字节。

     

调用此函数并返回结果的本机代码   byte-buffer对象到Java级代码应该确保缓冲区   是指可供阅读的有效记忆区域,   如果合适的话,写作。尝试访问无效内存   来自Java代码的位置将返回任意值,没有   可见效果,或导致抛出未指定的异常。

PS我们可以采取其他方式 - ByteBuffer有wrap方法,允许你包装byte[]的现有缓冲区,但不是char*,但我们可以将它们结合起来(看看这个answer)。

深入研究Jni方法:

 jsize n = sizeof(yourBuf);
 jbyteArray arr = (*env)->NewByteArray(env, n);
 (*env)->SetByteArrayRegion(env,arr,0,n, (jbyte*)yourBuf);

然而请注意,根据doc,此功能会导致复制,而不仅仅是包装,所以我在这里做的不太有用