如何将本机内存复制到 DirectByteBuffer
How to copy native memory to DirectByteBuffer
我知道一种方法——在 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);
但我想处理本机代码不复制数据,而只 returns 指向要复制的内存的指针的情况:
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()
对于这样的缓冲区是空的,因为它由本机内存区域支持。
请帮忙。
我找到了几种将 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);
重要的是要满足上面的断言条款。它保证指针是 jnr.ffi.provider.jffi.DirectMemoryIO
个实例,并且使用高效的 memcpy
方法进行复制(检查 DirectMemoryIO.transferTo()
的实现)。
另一种方法是使用以下方法包装 DirectByteBuffer
:
Pointer destPtr = Pointer.wrap(runtime, destAddress);
或
Pointer destPtr = Pointer.wrap(runtime, destAddress, size);
但没有:
指针 destPtr = Pointer.wrap(运行时,缓冲区);
第一个和第二个指针由 DirectMemoryIO
支持,但第三个指针由 ByteBufferMemoryIO
支持,它涉及缓慢的 byte-by-byte 复制。
一个缺点是 DirectMemoryIO
实例相当重量级。它在 JVM 堆上分配 32 个字节,因此在大量 JNR 调用的情况下,所有 DirectMemoryIO
个实例都会占用大部分内存。
我知道一种方法——在 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);
但我想处理本机代码不复制数据,而只 returns 指向要复制的内存的指针的情况:
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()
对于这样的缓冲区是空的,因为它由本机内存区域支持。
请帮忙。
我找到了几种将 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);
重要的是要满足上面的断言条款。它保证指针是 jnr.ffi.provider.jffi.DirectMemoryIO
个实例,并且使用高效的 memcpy
方法进行复制(检查 DirectMemoryIO.transferTo()
的实现)。
另一种方法是使用以下方法包装 DirectByteBuffer
:
Pointer destPtr = Pointer.wrap(runtime, destAddress);
或
Pointer destPtr = Pointer.wrap(runtime, destAddress, size);
但没有:
指针 destPtr = Pointer.wrap(运行时,缓冲区);
第一个和第二个指针由 DirectMemoryIO
支持,但第三个指针由 ByteBufferMemoryIO
支持,它涉及缓慢的 byte-by-byte 复制。
一个缺点是 DirectMemoryIO
实例相当重量级。它在 JVM 堆上分配 32 个字节,因此在大量 JNR 调用的情况下,所有 DirectMemoryIO
个实例都会占用大部分内存。