Reputation: 4378
Consider a header file defining this method:
ErrorCode_t GetBlob(Handle_const_t hHandle, uint8_t* const pValue, size_t* const pnSize);
This method writes n
bytes into the array starting at the pointer of pValue
. The size n
will be set at the pointer of pnSize
.
The header can be converted into Java source code using jextract, which gives:
public static long GetBlob(MemorySegment hHandle, MemorySegment pValue, MemorySegment pnSize) {
// ..
}
After reading https://stackoverflow.com/questions/76978598 and https://stackoverflow.com/questions/71250218 I allocated a C_POINTER
with unbounded address layout and called the method:
MemorySegment handle = ..;
MemorySegment arrayPointer = Arena.global().allocate(C_POINTER);
MemorySegment sizePointer = Arena.global().allocate(JAVA_LONG);
Accessor_h.GetBlob(handle, arrayPointer, sizePointer);
The call is successful. The sizePointer
contains the size of the array.
But reading the array data fails. I tried the following:
arrayPointer.get(C_POINTER, 0L)
.toArray(JAVA_BYTE); // fails with "Segment is too large to wrap as byte[]. Size: 9223372036854775807"
Or:
arrayPointer.get(C_POINTER, 0L)
.asSlice(0L, sizePointer.get(JAVA_LONG, 0L))
.toArray(JAVA_BYTE); // SIGSEGV (0xb)
Or:
arrayPointer
.toArray(JAVA_BYTE); // seems to contain the correct data, but only the first eight bytes
Or:
arrayPointer
.asSlice(0L, sizePointer.get(JAVA_LONG, 0L))
.toArray(JAVA_BYTE); // fails with "java.lang.IndexOutOfBoundsException: Out of bound access on segment MemorySegment"
What can I do, to safely read the byte array in Java?
Upvotes: 1
Views: 236
Reputation: 33895
The GetBlob
function looks to be writing bytes into the pValue
buffer you allocate with:
MemorySegment arrayPointer = Arena.global().allocate(C_POINTER);
This buffer is only 8
bytes in size (the size of C_POINTER.byteSize()
). This is likely not what you want. Instead, you probably want to allocate an array of bytes, e.g.:
long n = ...;
MemorySegment arrayPointer = Arena.global().allocate(uint8_t, n);
Where n
is the size of the buffer.
As for reading the result, your last attempt is the closest to being correct. Assuming that the array you allocate is larger than the size returned by the function.
long bytesWritten = sizePointer.get(JAVA_LONG, 0L);
byte[] arr = arrayPointer
.asSlice(0L, bytesWritten) // will do bounds check
.toArray(JAVA_BYTE);
If an IndexOutOfBoundsException
is thrown by asSlice
, it means that the GetBlob
function overflowed the buffer you allocated, because bytesWritten
would be larger than the buffer.
Upvotes: 0