我知道一种方法-在C ++方面使用memcpy
:
C ++方法:
void CopyData(void* buffer, int size)
{
memcpy(buffer, source, size);
}
JNR映射:
void CopyData(@Pinned @Out ByteBuffer byteBuffer, @Pinned @In int size);
Java调用:
ByteBuffer buffer = ByteBuffer.allocateDirect(size);
adapter.CopyData(buffer, size);
但是当本地代码不复制数据,而仅返回指向要复制的内存的指针时,我想处理这种情况:
C ++方法:
void* GetData1()
{
return source;
}
// or
struct Data
{
void* data;
};
void* GetData2(Data* outData)
{
outData->data = source;
}
我知道如何编写JNR映射,以便能够将数据复制到HeapByteBuffer
:
Pointer GetData1();
// or
void GetData2(@Pinned @Out Data outData);
final class Data extends Struct {
public final Struct.Pointer data;
public DecodeResult(Runtime runtime) {
super(runtime);
data = new Struct.Pointer();
}
}
Java调用:
ByteBuffer buffer = ByteBuffer.allocate(size);
Pointer dataPtr = adapter.GetData1();
dataPtr.get(0, buffer.array(), 0, buffer.array().length);
// or
ByteBuffer buffer = ByteBuffer.allocate(size);
Data outData = new Data(runtime);
adapter.GetData2(outData);
Pointer dataPtr = outData.data.get();
dataPtr.get(0, buffer.array(), 0, buffer.array().length);
但是我还没有找到一种将内存复制到DirectByteBuffer
而不是HeapByteBuffer
的方法。上面的代码段不适用于DirectByteBuffer
,因为buffer.array()
对于此类缓冲区为空,因为它由本机内存区域作为后援。
请帮助。
答案 0 :(得分:2)
我发现了几种将JNR本机内存复制到DirectByteBuffer
的方法。它们的效率不同。目前,我使用以下方法,但不知道它是JNR作者的最佳选择还是出于意图:
ByteBuffer buffer = ByteBuffer.allocateDirect(size);
Pointer dataPtr = adapter.GetData1();
long destAddress = ((DirectBuffer)buffer).address();
Pointer destPtr = AsmRuntime.pointerValue(destAddress, runtime);
assert dataPtr.isDirect() && destPtr.isDirect();
dataPtr.transferTo(0, destPtr, 0, size);
或
ByteBuffer buffer = ByteBuffer.allocateDirect(size);
Data outData = new Data(runtime);
adapter.GetData2(outData);
Pointer dataPtr = outData.data.get();
long destAddress = ((DirectBuffer)buffer).address();
Pointer destPtr = AsmRuntime.pointerValue(destAddress, runtime);
assert dataPtr.isDirect() && destPtr.isDirect();
dataPtr.transferTo(0, destPtr, 0, size);
重要的是,必须满足上面的assert子句。它保证了指针是jnr.ffi.provider.jffi.DirectMemoryIO
实例,并且有效的memcpy
方法用于复制(检查DirectMemoryIO.transferTo()
的实现)。
另一种方法是使用以下方法包装DirectByteBuffer
:
Pointer destPtr = Pointer.wrap(runtime, destAddress);
或
Pointer destPtr = Pointer.wrap(runtime, destAddress, size);
但没有:
Pointer destPtr = Pointer.wrap(运行时,缓冲区);
第一个和第二个指针由DirectMemoryIO
支持,但是第三个指针由ByteBufferMemoryIO
支持,并且涉及逐字节的慢速复制。
一个缺点是DirectMemoryIO
实例非常重。它在JVM堆上分配了32个字节,因此,在进行大量JNR调用的情况下,所有DirectMemoryIO
实例都会消耗大量内存。