SWIG 类型映射 uint8_t* 从 C/C++ 到 java.nio.ByteBuffer [英] SWIG typemap uint8_t* from C/C++ to java.nio.ByteBuffer

查看:51
本文介绍了SWIG 类型映射 uint8_t* 从 C/C++ 到 java.nio.ByteBuffer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to pass an input and an output buffer to a java class from C++. For efficiency reasons, I need to use a ByteBuffer.

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

Both of the buffers were allocated in the C++ part and I need to pass them to a java function that will use the input buffer for some computation and write the result into the output buffer.

以下是 C++ 的简化示例:

Here is an simplified example of how the C++ looks like:

// 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方面,我想实现这个(JavaDelegate类已经由SWIG生成):

On the Java side, I want to achieve this (JavaDelegate class has been generated by SWIG):

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++,但我不知道如何反向操作.

The problem is, I simply can't figure out how to do the typemaps to wrap a plain char* to a ByteBuffer, especially in conjunction with SWIG's director feature turned on for the abstract baseclass. I know how to pass a ByteBuffer from Java to C++ but I can't find out how to do the reverse.

感谢任何帮助!

推荐答案

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

Preface: this is not SWIG-ish solution, this is general purpose, I found this somewhat related to your question

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

First, there are no ref parameters in Java as far as I know so passing it directly from C++ is not an option unless you are ready to change your signature and have it as a return value. This would be possible to circumvent by passing typewrapper from Java and having C++ creating/setting buffer inside it, a la:

public class BufferWrapper {
    private ByteBuffer mBuffer;

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

只需将其传递给 C++ 并让它分配并将缓冲区设置为包装器.

Just pass this to C++ and have it allocate and set buffer to wrapper.

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

There's NewDirectByteBuffer JNI function that does exactly what you need:

分配并返回一个直接引用 java.nio.ByteBuffer 的 java.nio.ByteBuffer从内存地址地址开始并扩展的内存块容量字节.

Allocates and returns a direct java.nio.ByteBuffer referring to the block of memory starting at the memory address address and extending capacity bytes.

调用此函数并返回结果的本机代码字节缓冲区对象到 Java 级代码应确保缓冲区指可读取的有效内存区域,并且,如果合适,写作.尝试访问无效内存来自 Java 代码的 location 将返回一个任意值,没有可见效果,或导致抛出未指定的异常.

Native code that calls this function and returns the resulting byte-buffer object to Java-level code should ensure that the buffer refers to a valid region of memory that is accessible for reading and, if appropriate, writing. An attempt to access an invalid memory location from Java code will either return an arbitrary value, have no visible effect, or cause an unspecified exception to be thrown.

<小时>

PS 我们可以走其他方式 - ByteBuffer 有 wrap 方法,它允许你包装 byte[] 的现有缓冲区,它不完全是 char* 但我们可以结婚他们(看看这个 answer).


P.S we could have gone other way - ByteBuffer has wrap method that would allow you to wrap existing buffer of byte[] which is not exactly char* but we could marry them (look at this answer).

深入了解您的 Jni 方法实现:

In depth of your Jni method implmentation:

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

但是请注意,根据 doc 这个函数会导致复制而不仅仅是包装,所以我认为它在这里不是很有帮助

However note that according to doc this function incurs copy not just wrapping so I doom it not very helpful here

这篇关于SWIG 类型映射 uint8_t* 从 C/C++ 到 java.nio.ByteBuffer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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