Your code looks almost correct to me. You just need to keep hold of the allocated segment (which represents the heif_image_handle**
), and then after calling heif_context_get_primary_image_handle
, retrieve the MemoryAddress
from that segment after the library sets the primary image handle into it (example using the JDK 17 API):
// allocate blob of memory the size of a pointer
MemorSegment primary_image_handle_seg = MemorySegment.allocateNative(C_POINTER);
// call library to set the handle into the allocated memory
heif_context_get_primary_image_handle(ctx, primary_image_handle_seg.address());
// retrieve pointer from allocated memory
MemoryAddress primary_image_handle = MemoryAccess.getAddress(primary_image_handle_seg);
In general, doing stack allocations and taking the address of the allocated value like in C, as in the snippet that you show, is not possible directly in Java. So, as far as the panama foreign API goes, whenever you see something like this in C code:
some_type* val;
You will need to allocate a MemorySegment
for it:
// some_type** val_ptr;
MemorySegment val_ptr = MemerySegment.allocateNative(C_POINTER, scope);
// some_type** val_ptr_as_ma; (as a bare MemoryAddress)
MemoryAddress val_ptr_as_ma = val.address();
// some_type* val; (dereference/copy val, `*val_ptr`)
MemoryAddress val = MemoryAccess.getAddress(val);
Note that we have to go through the MemorySegment
route in this case. Since it is not possible to take the address of a MemoryAddress
.
In general, the Java API does not have an equivalent of the &
ampersand operator. The .address()
method is there to convert address-like things into MemoryAddress
instances, not to mimic &
. And for MemoryAddress
itself it just return this
(so your primary_image_handle.address()
call has no effect).
Essentially, the C equivalent of what we do in Java, without stack allocation and &
, is this:
some_type** val_ptr = malloc(sizeof *val_ptr);
func(val_ptr); // void func(some_type** v) { ... }
some_type* val = *val_ptr;