java - SWIG 类型映射 uint8_t* 从 C/C++ 到 java.nio.ByteBuffer

标签 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 方面,我想实现这个(JavaDelegate 类已由 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++,但我不知道如何执行相反的操作。

感谢任何帮助!

最佳答案

前言:这不是 SWIG-ish 解决方案,这是通用的,我找到了 this与你的问题有些相关


首先,据我所知,Java 中没有ref 参数,因此直接从 C++ 传递它不是一种选择,除非您准备好更改您的签名并将其作为返回值。这可以通过从 Java 传递 typewrapper 并在其中使用 C++ 创建/设置缓冲区来规避,a la:

public class BufferWrapper {
    private ByteBuffer mBuffer;

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

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

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

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

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.


P.S 我们本可以采用其他方式 - 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此函数会产生复制,而不仅仅是包装,所以我认为它在这里不是很有用

关于java - SWIG 类型映射 uint8_t* 从 C/C++ 到 java.nio.ByteBuffer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41301653/

相关文章:

c++ - 如何将 vector<bool> 或 bitset 按位存储到文件中?

c++ - 在 C++ 中使用初始化列表时的奇怪行为

python - SWIG Python 绑定(bind)到本地代码不适用于 OpenCV 2.1

Java HashMap 逆向方式

java - 按值对java映射进行排序(包含一个集合)

Java游戏鼠标移动

c++ - 正则表达式 : group for every found item (PCRE)

python - 从 C++.so 调用 python 文件时出现段错误(核心已转储)

c++ - 如何使用 autotools 在构建库的同时构建 Python 接口(interface)

java - Tomcat 5.5 找不到我的 Servlet