我正在尝试将输入和输出缓冲区从 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/