zero-length segments
Michael Zucchi
notzed at gmail.com
Thu Jan 20 22:50:28 UTC 2022
Morning all,
After a long break i've started experimenting with the foreign abi to
replace jni. One tool i'm working on is a vulkan binding generator that
works directly from the xml specification and generates a 'nice' api
(particularly focusing on constructors for all the hundreds of
configuration structures needed for vulkan, plus the dynamic function
tables), and another tool generates high-level and potentially object
oriented api's from c header files, for this one I use a gcc plugin to
extract the structures and functions and i'm trying opencl and ffmpeg as
test cases (and to update some projects i maintain, zcl and jjmpeg).
I'm not using jextract because I want to create the high level api
directly and provide much more control on the created classes, and also
because i've got the time and nothing better to do with it.
In general it looks pretty good after so much work, but i've come across
one oddity which adds complexity to the java code for no obvious
reason. Is there any specific reason you cannot create zero length
memory segments *in some cases*?
e.g. something like this comes up often in C:
struct blob {
size_t data_size;
uint8_t *data;
}
From java at some point you want to get a MemorySegment to access
blob.data. It might be through a high level api such as:
class blob {
MemorySegment getData() {
return MemorySegment.ofAddress(...);
}
}
If the memory was allocated in the native code (quite common) this
obvious java-side implementation just isn't possible with the current
MemorySegment implementation as it will fail in an unexpected (and imho
unreasonable) way if size is 0. You'd either need to wrap MemorySegment
in some other structure which hides this detail with it's own special
case code (seems redundant), return a null (apparently evil these days,
and kinda messy anyway), or expose the detail by ensuring the callee
checks size>0 before calling getData() (yikes).
One notes that it is inconsistent with the rest of the api:
works:
segmentAllocator.allocate(MemoryLayout.structLayout().withBitAlignment(8))
works: segmentAllocator.allocateArray(JAVA_BYTE, 0);
works: segmentAllocator.allocate(0);
works: segment.asSlice(offset, 0);
works: MemorySegment.ofArray(new byte[0]);
works: MemorySegment.ofByteBuffer(ByteBuffer.allocateDirect(0));
(you get the idea ...)
doesn't:
MemorySegment.allocateNative(MemoryLayout.structLayout().withBitAlignment(8),
scope);
doesn't: MemorySegment.allocateNative(0, 1, scope);
doesn't: MemorySegment.ofAddress(addr, 0, scope);
With the last one being the only way to wrap sized-allocations from
native memory(?) there seems to be no workaround possible.
Both java and c specifically define zero-length allocations as valid
everywhere else because it simplifies a lot of code, and even the
foreign-abi does for every other case, so why not here too?
Cheers,
Z
More information about the panama-dev
mailing list