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