Mapping List<String> to char **

Sebastian Stenzel sebastian.stenzel at gmail.com
Fri Jun 11 15:21:50 UTC 2021


Awesome, thank you!

> On 11. Jun 2021, at 16:50, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
> 
> Hi,
> The API we have in 17 has the ability to create a so called SegmentAllocator:
> 
> https://download.java.net/java/early_access/jdk17/docs/api/jdk.incubator.foreign/jdk/incubator/foreign/SegmentAllocator.html
> 
> A SegmentAllocator has a method to allocate a contiguous array of addresses:
> 
> https://download.java.net/java/early_access/jdk17/docs/api/jdk.incubator.foreign/jdk/incubator/foreign/SegmentAllocator.html#allocateArray(jdk.incubator.foreign.ValueLayout,jdk.incubator.foreign.Addressable%5B%5D)
> 
> I believe that by combining these bits you should be able to do what you want - e.g.
> 
> ```
> jshell> import jdk.incubator.foreign.*;
> 
> jshell> List<String> strings = List.of("a", "b", "c");
> strings ==> [a, b, c]
> 
> jshell> var scope = ResourceScope.newConfinedScope();
> scope ==> jdk.internal.foreign.ConfinedScope at 37f8bb67
> 
> jshell> var allocator = SegmentAllocator.ofScope(scope);
> allocator ==> jdk.internal.foreign.ConfinedScope at 37f8bb67
> 
> jshell> var cstrings = allocator.allocateArray(CLinker.C_POINTER, strings.stream().map(s -> CLinker.toCString(s, scope)).toArray(Addressable[]::new));
> cstrings ==> MemorySegment{ id=0x72ee5071 limit: 24 }
> 
> jshell> CLinker.toJavaString(MemoryAccess.getAddressAtIndex(cstrings, 0));
> $6 ==> "a"
> 
> jshell> CLinker.toJavaString(MemoryAccess.getAddressAtIndex(cstrings, 1));
> $7 ==> "b"
> 
> jshell> CLinker.toJavaString(MemoryAccess.getAddressAtIndex(cstrings, 2));
> $8 ==> "c"
> ```
> 
> I hope this helps.
> 
> Maurizio
> 
> On 11/06/2021 15:32, Sebastian Stenzel wrote:
>> Hi,
>> 
>> imagine you want to invoke a native method with (among others) these params:
>> 
>>     int argc, char **argv
>> 
>> On the Java side I have a `List<String>`.
>> 
>> Currently, ...
>> 
>> 1. I create a new SequenceLayout of type MemoryLayouts.ADDRESS and of size `argc`
>> 2. I allocate a new MemorySegment `argv` using aforementioned layout
>> 3. For each of my elements, I call CLinker.toCString and fill in the address of the returned segment into `argv`
>> 
>> I feel like there should be an easier way to achieve this. Is there some utility to create a MemorySegment from an array of addresses? (I know I can create an array of longs, but I don't want to rely on a 64 bit architecture).
>> 
>> Thanks,
>> Sebastian



More information about the panama-dev mailing list