From bfb87f84503337c7b61b016cf19fe930612f6361 Mon Sep 17 00:00:00 2001 From: Nizar Benalla Date: Wed, 4 Feb 2026 17:17:58 +0100 Subject: [PATCH 1/2] add new reinterpret method that keeps scope --- .../openjdk/jextract/impl/StructBuilder.java | 14 +++++++------- .../generator/reinterpret/TestReinterpret.java | 17 +++++++++++++++-- .../test8257892/LibUnsupportedTest.java | 4 ++-- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/openjdk/jextract/impl/StructBuilder.java b/src/main/java/org/openjdk/jextract/impl/StructBuilder.java index 4081e433..c42e791b 100644 --- a/src/main/java/org/openjdk/jextract/impl/StructBuilder.java +++ b/src/main/java/org/openjdk/jextract/impl/StructBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -359,18 +359,18 @@ private void emitReinterpret() { /** * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). - * The returned segment has size {@code layout().byteSize()} + * The returned segment has size {@code elementCount * layout().byteSize()} */ - public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { - return reinterpret(addr, 1, arena, cleanup); + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); } /** - * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * Reinterprets {@code addr} using the existing scope. * The returned segment has size {@code elementCount * layout().byteSize()} */ - public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { - return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); + public static MemorySegment reinterpret(MemorySegment addr, long elementCount) { + return addr.reinterpret(layout().byteSize() * elementCount); } """); } diff --git a/test/jtreg/generator/reinterpret/TestReinterpret.java b/test/jtreg/generator/reinterpret/TestReinterpret.java index 125886d6..f18f5a93 100644 --- a/test/jtreg/generator/reinterpret/TestReinterpret.java +++ b/test/jtreg/generator/reinterpret/TestReinterpret.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ public class TestReinterpret { public void testSingleStruct() { try (Arena arena = Arena.ofConfined()) { MemorySegment addr = make(14, 99); - MemorySegment seg = Point.reinterpret(addr, arena, reinterpret_h::freePoint); + MemorySegment seg = Point.reinterpret(addr, 1, arena, reinterpret_h::freePoint); assertEquals(Point.x(seg), 14); assertEquals(Point.y(seg), 99); } @@ -64,4 +64,17 @@ public void testStructArray() { } } } + + @Test + public void testReinterpretScope() { + try (Arena arena = Arena.ofConfined()) { + MemorySegment addr = make(14, 99); + MemorySegment seg = Point.reinterpret(addr, 1); + assertEquals(Point.x(seg), 14); + assertEquals(Point.y(seg), 99); + + MemorySegment array = Point.reinterpret(addr, 2); + assertEquals(array.byteSize(), Point.layout().byteSize() * 2); + } + } } diff --git a/test/jtreg/generator/test8257892/LibUnsupportedTest.java b/test/jtreg/generator/test8257892/LibUnsupportedTest.java index 283a6bdd..02696cf6 100644 --- a/test/jtreg/generator/test8257892/LibUnsupportedTest.java +++ b/test/jtreg/generator/test8257892/LibUnsupportedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ public void testAllocateFoo() { @Test public void testGetFoo() { try (Arena arena = Arena.ofConfined()) { - var seg = Foo.reinterpret(getFoo(), arena, null); + var seg = Foo.reinterpret(getFoo(), 1, arena, null); Foo.i(seg, 42); Foo.c(seg, (byte)'j'); assertEquals(Foo.i(seg), 42); From 59a17381479948b5bbf88320fe83642e5e424301 Mon Sep 17 00:00:00 2001 From: Nizar Benalla Date: Wed, 1 Apr 2026 17:41:58 +0100 Subject: [PATCH 2/2] update guide --- doc/GUIDE.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/doc/GUIDE.md b/doc/GUIDE.md index 9f866f76..4e3494d8 100644 --- a/doc/GUIDE.md +++ b/doc/GUIDE.md @@ -328,10 +328,9 @@ public class Point {     public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { ... } // 4 - public static MemorySegment reinterpret(MemorySegment addr, Arena arena, - Consumer cleanup) { ... } // 6     public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { ... } // 6 +    public static MemorySegment reinterpret(MemorySegment addr, long elementCount) { ... } // 6 } ``` @@ -406,17 +405,24 @@ The `reinterpret` method can be used to associate the correct bounds and lifetim // Main.java try (Arena arena = Arena.ofConfined()) { - MemorySegment point = Point.reinterpret(new_point(), arena, mylib_h::delete_point); + MemorySegment point = Point.reinterpret(new_point(), 1, arena, mylib_h::delete_point); // ... } // 'delete_point` called here ``` The `point` segment returned by `reinterpret` has exactly the size of one `Point` (for -arrays of struct, use the `reinterpret` overload that takes an element count as well). The -lifetime we associate with the segment is the lifetime denoted by `arena`, and when the -arena is closed, we want to call `delete_point`, which we can do by passing a method -reference to `delete_point` as a cleanup action when calling `reinterpret`. +arrays of struct, pass a larger `elementCount`). The lifetime we associate with the segment +is the lifetime denoted by `arena`, and when the arena is closed, we want to call +`delete_point`, which we can do by passing a method reference to `delete_point` as a cleanup +action when calling `reinterpret`. + +If the source segment already has the desired scope and you only need to adjust the bounds, use +the overload that keeps the existing scope: + +```java +MemorySegment points = Point.reinterpret(existingSegment, elementCount); +``` The class that jextract generates for unions is identical to the class generated for structs.