Mapping List<String> to char **

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Jun 11 14:50:10 UTC 2021


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