Porting JNA code to Foreign Function & Memory API (FFM) (Java 19, JEP 424), fails for String[] returned array from C
C API:
int nc_get_att_string(
int ncid,
int varid,
const char * name,
char ** value)
"Note that unlike most other nc_get_att functions, nc_get_att_string() allocates a chunk of memory which is returned to the calling function. This chunk of memory must be specifically deallocated with nc_free_string() to avoid any memory leaks. Also note that you must still preallocate the memory needed for the array of pointers passed to nc_get_att_string()."
So, one passes an array of char* pointers, and the library returns an array of strings. I have this working in JNA in Java:
String[] valss = new String[len];
ret = nc4.nc_get_att_string(grpid, varid, attname, valss);
if (ret != 0)
throw new IOException(ret + ": " + nc4.nc_strerror(ret));
return valss;
But trying to do the equivilent in the Foreign Function & Memory API in Kotlin fails:
val strings_p : MemorySegment = session.allocateArray(ValueLayout.ADDRESS, nelems)
checkErr("nc_get_att_string", nc_get_att_string(grpid, varid, attname, strings_p))
val result = mutableListOf<String>()
for (i in 0 until nelems) {
val s2 : MemoryAddress = strings_p.getAtIndex(ValueLayout.ADDRESS, i)
val s = s2.getUtf8String(0) // FAILS here
result.add(s)
}
return result
fails with:
Symbol is NULL: MemoryAddress{ offset=0x0 }
java.lang.IllegalArgumentException: Symbol is NULL: MemoryAddress{ offset=0x0 }
at java.base/jdk.internal.foreign.abi.SharedUtils.checkAddressable(SharedUtils.java:344)
at java.base/jdk.internal.foreign.abi.SharedUtils.checkAddress(SharedUtils.java:338)
at java.base/jdk.internal.foreign.MemoryAddressImpl.getUtf8String(MemoryAddressImpl.java:107)
at sunya.cdm.netcdfClib.NCheader.readAttributeValues(NCheader.kt:365)
Anyone see what Im doing wrong?
The problem is with the installed C library, and the JNA code sees the same thing. Sorry for the misdirection.