Skip to content

Commit 2f6b9ab

Browse files
committedFeb 1, 2024
7903649: Field and global variables of array type should have indexed accessors
Reviewed-by: jvernee
1 parent 9412a2f commit 2f6b9ab

File tree

9 files changed

+648
-84
lines changed

9 files changed

+648
-84
lines changed
 

‎src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java

+14
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@
4040
import java.lang.invoke.MethodHandle;
4141
import java.lang.invoke.MethodType;
4242
import java.lang.invoke.VarHandle;
43+
import java.util.List;
4344
import java.util.Objects;
4445
import java.util.stream.Collectors;
46+
import java.util.stream.IntStream;
4547

4648
/**
4749
* Superclass for .java source generator classes.
@@ -266,4 +268,16 @@ static String declarationComment(Declaration decl) {
266268
String declString = DeclarationString.getOrThrow(decl);
267269
return declString.lines().collect(Collectors.joining("\n * ", " * ", ""));
268270
}
271+
272+
record IndexList(String decl, String use) {
273+
static IndexList of(int dims) {
274+
List<String> indexNames = IntStream.range(0, dims).mapToObj(i -> "index" + i).toList();
275+
String indexDecls = indexNames.stream()
276+
.map(i -> "long " + i)
277+
.collect(Collectors.joining(", "));
278+
String indexUses = indexNames.stream()
279+
.collect(Collectors.joining(", "));
280+
return new IndexList(indexDecls, indexUses);
281+
}
282+
}
269283
}

‎src/main/java/org/openjdk/jextract/impl/HeaderFileBuilder.java

+168-59
Large diffs are not rendered by default.

‎src/main/java/org/openjdk/jextract/impl/StructBuilder.java

+115-17
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.util.Deque;
4343
import java.util.List;
4444
import java.util.stream.Collectors;
45+
import java.util.stream.IntStream;
4546

4647
/**
4748
* This class generates static utilities class for C structs, unions.
@@ -133,13 +134,21 @@ public void addFunctionalInterface(Declaration parentDecl, Type.Function funcTyp
133134
public void addVar(Declaration.Variable varTree) {
134135
String javaName = JavaName.getOrThrow(varTree);
135136
appendBlankLine();
136-
String offsetField = emitOffsetFieldDecl(varTree);
137+
String layoutField = emitLayoutFieldDecl(varTree, javaName);
138+
appendBlankLine();
139+
String offsetField = emitOffsetFieldDecl(varTree, javaName);
137140
if (Utils.isArray(varTree.type()) || Utils.isStructOrUnion(varTree.type())) {
138-
String sizeField = emitSizeFieldDecl(varTree);
139-
emitSegmentGetter(javaName, varTree, offsetField, sizeField);
140-
emitSegmentSetter(javaName, varTree, offsetField, sizeField);
141+
emitSegmentGetter(javaName, varTree, offsetField, layoutField);
142+
emitSegmentSetter(javaName, varTree, offsetField, layoutField);
143+
int dims = Utils.dimensions(varTree.type()).size();
144+
if (dims > 0) {
145+
emitDimensionsFieldDecl(varTree, javaName);
146+
String arrayHandle = emitArrayElementHandle(javaName, varTree, layoutField, dims);
147+
IndexList indexList = IndexList.of(dims);
148+
emitFieldArrayGetter(javaName, varTree, arrayHandle, indexList);
149+
emitFieldArraySetter(javaName, varTree, arrayHandle, indexList);
150+
}
141151
} else if (Utils.isPointer(varTree.type()) || Utils.isPrimitive(varTree.type())) {
142-
String layoutField = emitLayoutFieldDecl(varTree);
143152
emitFieldGetter(javaName, varTree, layoutField, offsetField);
144153
emitFieldSetter(javaName, varTree, layoutField, offsetField);
145154
} else {
@@ -199,29 +208,94 @@ private void emitFieldSetter(String javaName, Declaration.Variable varTree, Stri
199208
""");
200209
}
201210

202-
private void emitSegmentGetter(String javaName, Declaration.Variable varTree, String offsetField, String sizeField) {
211+
private void emitSegmentGetter(String javaName, Declaration.Variable varTree, String offsetField, String layoutField) {
203212
appendBlankLine();
204213
emitFieldDocComment(varTree, "Getter for field:");
205214
String segmentParam = safeParameterName(kindName());
206215
appendIndentedLines(STR."""
207216
public static MemorySegment \{javaName}(MemorySegment \{segmentParam}) {
208-
return \{segmentParam}.asSlice(\{offsetField}, \{sizeField});
217+
return \{segmentParam}.asSlice(\{offsetField}, \{layoutField}.byteSize());
209218
}
210219
""");
211220
}
212221

213-
private void emitSegmentSetter(String javaName, Declaration.Variable varTree, String offsetField, String sizeField) {
222+
private void emitSegmentSetter(String javaName, Declaration.Variable varTree, String offsetField, String layoutField) {
214223
appendBlankLine();
215224
emitFieldDocComment(varTree, "Setter for field:");
216225
String segmentParam = safeParameterName(kindName());
217226
String valueParam = safeParameterName("fieldValue");
218227
appendIndentedLines(STR."""
219228
public static void \{javaName}(MemorySegment \{segmentParam}, MemorySegment \{valueParam}) {
220-
MemorySegment.copy(\{valueParam}, 0L, \{segmentParam}, \{offsetField}, \{sizeField});
229+
MemorySegment.copy(\{valueParam}, 0L, \{segmentParam}, \{offsetField}, \{layoutField}.byteSize());
221230
}
222231
""");
223232
}
224233

234+
private String emitArrayElementHandle(String javaName, Declaration.Variable varTree, String fieldLayoutName, int dims) {
235+
String arrayHandleName = STR."\{javaName}$ELEM_HANDLE";
236+
String path = IntStream.range(0, dims)
237+
.mapToObj(_ -> "sequenceElement()")
238+
.collect(Collectors.joining(", "));
239+
Type elemType = Utils.typeOrElemType(varTree.type());
240+
if (Utils.isStructOrUnion(elemType)) {
241+
appendIndentedLines(STR."""
242+
private static final MethodHandle \{arrayHandleName} = \{fieldLayoutName}.sliceHandle(\{path});
243+
""");
244+
} else {
245+
appendIndentedLines(STR."""
246+
private static final VarHandle \{arrayHandleName} = \{fieldLayoutName}.varHandle(\{path});
247+
""");
248+
}
249+
return arrayHandleName;
250+
}
251+
252+
private void emitFieldArrayGetter(String javaName, Declaration.Variable varTree, String arrayElementHandle, IndexList indexList) {
253+
String segmentParam = safeParameterName(kindName());
254+
Type elemType = Utils.typeOrElemType(varTree.type());
255+
Class<?> elemTypeCls = Utils.carrierFor(elemType);
256+
appendBlankLine();
257+
emitFieldDocComment(varTree, "Indexed getter for field:");
258+
if (Utils.isStructOrUnion(elemType)) {
259+
appendIndentedLines(STR."""
260+
public static MemorySegment \{javaName}(MemorySegment \{segmentParam}, \{indexList.decl()}) {
261+
try {
262+
return (MemorySegment)\{arrayElementHandle}.invokeExact(\{segmentParam}, 0L, \{indexList.use()});
263+
} catch (Throwable ex$) {
264+
throw new AssertionError("should not reach here", ex$);
265+
}
266+
}
267+
""");
268+
} else {
269+
appendIndentedLines(STR."""
270+
public static \{elemTypeCls.getSimpleName()} \{javaName}(MemorySegment \{segmentParam}, \{indexList.decl()}) {
271+
return (\{elemTypeCls.getSimpleName()})\{arrayElementHandle}.get(\{segmentParam}, 0L, \{indexList.use()});
272+
}
273+
""");
274+
}
275+
}
276+
277+
private void emitFieldArraySetter(String javaName, Declaration.Variable varTree, String arrayElementHandle, IndexList indexList) {
278+
String segmentParam = safeParameterName(kindName());
279+
String valueParam = safeParameterName("fieldValue");
280+
Type elemType = Utils.typeOrElemType(varTree.type());
281+
Class<?> elemTypeCls = Utils.carrierFor(elemType);
282+
appendBlankLine();
283+
emitFieldDocComment(varTree, "Indexed setter for field:");
284+
if (Utils.isStructOrUnion(elemType)) {
285+
appendIndentedLines(STR."""
286+
public static void \{javaName}(MemorySegment \{segmentParam}, \{indexList.decl()}, MemorySegment \{valueParam}) {
287+
MemorySegment.copy(\{valueParam}, 0L, \{javaName}(\{segmentParam}, \{indexList.use()}), 0L, \{layoutString(elemType)}.byteSize());
288+
}
289+
""");
290+
} else {
291+
appendIndentedLines(STR."""
292+
public static void \{javaName}(MemorySegment \{segmentParam}, \{indexList.decl()}, \{elemTypeCls.getSimpleName()} \{valueParam}) {
293+
\{arrayElementHandle}.set(\{segmentParam}, 0L, \{indexList.use()}, \{valueParam});
294+
}
295+
""");
296+
}
297+
}
298+
225299
private void emitAsSlice() {
226300
String arrayParam = safeParameterName("array");
227301
appendIndentedLines(STR."""
@@ -309,29 +383,53 @@ public static final GroupLayout layout() {
309383
""");
310384
}
311385

312-
private String emitOffsetFieldDecl(Declaration field) {
313-
String offsetFieldName = STR."\{field.name()}$OFFSET";
386+
private String emitOffsetFieldDecl(Declaration.Variable field, String javaName) {
387+
String offsetFieldName = STR."\{javaName}$OFFSET";
314388
appendIndentedLines(STR."""
315389
private static final long \{offsetFieldName} = \{ClangOffsetOf.getOrThrow(field) / 8};
316390
""");
391+
appendBlankLine();
392+
emitFieldDocComment(field, "Offset for field:");
393+
appendIndentedLines(STR."""
394+
public static final long \{javaName}$offset() {
395+
return \{offsetFieldName};
396+
}
397+
""");
317398
return offsetFieldName;
318399
}
319400

320-
private String emitLayoutFieldDecl(Declaration.Variable field) {
321-
String layoutFieldName = STR."\{field.name()}$LAYOUT";
401+
private String emitLayoutFieldDecl(Declaration.Variable field, String javaName) {
402+
String layoutFieldName = STR."\{javaName}$LAYOUT";
322403
String layoutType = Utils.layoutCarrierFor(field.type()).getSimpleName();
323404
appendIndentedLines(STR."""
324405
private static final \{layoutType} \{layoutFieldName} = (\{layoutType})$LAYOUT.select(\{fieldElementPaths(field.name())});
325406
""");
407+
appendBlankLine();
408+
emitFieldDocComment(field, "Layout for field:");
409+
appendIndentedLines(STR."""
410+
public static final \{layoutType} \{javaName}$layout() {
411+
return \{layoutFieldName};
412+
}
413+
""");
326414
return layoutFieldName;
327415
}
328416

329-
private String emitSizeFieldDecl(Declaration field) {
330-
String sizeFieldName = STR."\{field.name()}$SIZE";
417+
private void emitDimensionsFieldDecl(Declaration.Variable field, String javaName) {
418+
String dimsFieldName = STR."\{javaName}$DIMS";
419+
List<Long> dimensions = Utils.dimensions(field.type());
420+
String dimsString = dimensions.stream().map(d -> d.toString())
421+
.collect(Collectors.joining(", "));
331422
appendIndentedLines(STR."""
332-
private static final long \{sizeFieldName} = \{ClangSizeOf.getOrThrow(field) / 8};
423+
424+
private static long[] \{dimsFieldName} = { \{dimsString} };
425+
""");
426+
appendBlankLine();
427+
emitFieldDocComment(field, "Dimensions for array field:");
428+
appendIndentedLines(STR."""
429+
public static long[] \{javaName}$dimensions() {
430+
return \{dimsFieldName};
431+
}
333432
""");
334-
return sizeFieldName;
335433
}
336434

337435
private String structOrUnionLayoutString(Type type) {

‎src/main/java/org/openjdk/jextract/impl/Utils.java

+19
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import java.lang.foreign.SequenceLayout;
4747
import java.lang.foreign.ValueLayout;
4848
import java.lang.invoke.MethodType;
49+
import java.util.ArrayList;
50+
import java.util.List;
4951
import java.util.Map;
5052
import java.util.function.Consumer;
5153

@@ -183,6 +185,23 @@ static Type.Primitive getAsSignedOrUnsigned(Type type) {
183185
return null;
184186
}
185187

188+
static List<Long> dimensions(Type type) {
189+
List<Long> dims = new ArrayList<>();
190+
while (type instanceof Type.Array array) {
191+
if (array.elementCount().isEmpty()) return List.of();
192+
dims.add(array.elementCount().getAsLong());
193+
type = array.elementType();
194+
}
195+
return dims;
196+
}
197+
198+
static Type typeOrElemType(Type type) {
199+
return switch (type) {
200+
case Type.Array array -> typeOrElemType(array.elementType());
201+
default -> type;
202+
};
203+
}
204+
186205
/**
187206
* Is a character printable ASCII?
188207
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import org.testng.annotations.Test;
25+
26+
import static org.testng.Assert.*;
27+
28+
import test.jextract.arrayaccess.*;
29+
30+
import java.lang.foreign.Arena;
31+
import java.lang.foreign.MemorySegment;
32+
33+
import static test.jextract.arrayaccess.array_access_h.*;
34+
35+
/*
36+
* @test
37+
* @library /lib
38+
* @run main/othervm JtregJextract -l ArrayAccess -t test.jextract.arrayaccess array_access.h
39+
* @build TestArrayAccess
40+
* @run testng/othervm --enable-native-access=ALL-UNNAMED TestArrayAccess
41+
*/
42+
43+
public class TestArrayAccess {
44+
@Test
45+
public void testArrayAccessStructInt1() {
46+
try (Arena arena = Arena.ofConfined()) {
47+
MemorySegment foo = Foo.allocate(arena);
48+
long[] dims = Foo.ints1$dimensions();
49+
for (int i = 0 ; i < dims[0] ; i++) {
50+
Foo.ints1(foo, i, i + 1);
51+
assertEquals(Foo.ints1(foo, i), i + 1);
52+
}
53+
}
54+
}
55+
56+
@Test
57+
public void testArrayAccessStructInt2() {
58+
try (Arena arena = Arena.ofConfined()) {
59+
MemorySegment foo = Foo.allocate(arena);
60+
long[] dims = Foo.ints2$dimensions();
61+
for (int i = 0 ; i < dims[0] ; i++) {
62+
for (int j = 0; j < dims[1]; j++) {
63+
Foo.ints2(foo, i, j, i + j + 1);
64+
assertEquals(Foo.ints2(foo, i, j), i + j + 1);
65+
}
66+
}
67+
}
68+
}
69+
70+
@Test
71+
public void testArrayAccessStructInt3() {
72+
try (Arena arena = Arena.ofConfined()) {
73+
MemorySegment foo = Foo.allocate(arena);
74+
long[] dims = Foo.ints3$dimensions();
75+
for (int i = 0 ; i < dims[0] ; i++) {
76+
for (int j = 0; j < dims[1]; j++) {
77+
for (int k = 0; k < dims[2]; k++) {
78+
Foo.ints3(foo, i, j, k, i + j + k + 1);
79+
assertEquals(Foo.ints3(foo, i, j, k), i + j + k + 1);
80+
}
81+
}
82+
}
83+
}
84+
}
85+
86+
@Test
87+
public void testArrayAccessGlobalInt1() {
88+
long[] dims = ints1$dimensions();
89+
for (int i = 0 ; i < dims[0] ; i++) {
90+
ints1(i, i + 1);
91+
assertEquals(ints1(i), i + 1);
92+
}
93+
}
94+
95+
@Test
96+
public void testArrayAccessGlobalInt2() {
97+
long[] dims = ints2$dimensions();
98+
for (int i = 0 ; i < dims[0] ; i++) {
99+
for (int j = 0; j < dims[1]; j++) {
100+
ints2(i, j, i + j + 1);
101+
assertEquals(ints2(i, j), i + j + 1);
102+
}
103+
}
104+
}
105+
106+
@Test
107+
public void testArrayAccessGlobalInt3() {
108+
long[] dims = ints3$dimensions();
109+
for (int i = 0 ; i < dims[0] ; i++) {
110+
for (int j = 0; j < dims[1]; j++) {
111+
for (int k = 0; k < dims[2]; k++) {
112+
ints3(i, j, k, i + j + k + 1);
113+
assertEquals(ints3(i, j, k), i + j + k + 1);
114+
}
115+
}
116+
}
117+
}
118+
119+
@Test
120+
public void testArrayAccessStructStruct1() {
121+
try (Arena arena = Arena.ofConfined()) {
122+
MemorySegment foo = Foo.allocate(arena);
123+
long[] dims = Foo.points1$dimensions();
124+
for (int i = 0 ; i < dims[0] ; i++) {
125+
MemorySegment point = Point.allocate(arena);
126+
Point.x(point, i + 1);
127+
Point.y(point, i + 2);
128+
Foo.points1(foo, i, point);
129+
assertEquals(Point.x(Foo.points1(foo, i)), i + 1);
130+
assertEquals(Point.y(Foo.points1(foo, i)), i + 2);
131+
}
132+
}
133+
}
134+
135+
@Test
136+
public void testArrayAccessStructStruct2() {
137+
try (Arena arena = Arena.ofConfined()) {
138+
MemorySegment foo = Foo.allocate(arena);
139+
long[] dims = Foo.points2$dimensions();
140+
for (int i = 0 ; i < dims[0] ; i++) {
141+
for (int j = 0; j < dims[1]; j++) {
142+
MemorySegment point = Point.allocate(arena);
143+
Point.x(point, i + j + 1);
144+
Point.y(point, i + j + 2);
145+
Foo.points2(foo, i, j, point);
146+
assertEquals(Point.x(Foo.points2(foo, i, j)), i + j + 1);
147+
assertEquals(Point.y(Foo.points2(foo, i, j)), i + j + 2);
148+
}
149+
}
150+
}
151+
}
152+
153+
@Test
154+
public void testArrayAccessStructStruct3() {
155+
try (Arena arena = Arena.ofConfined()) {
156+
MemorySegment foo = Foo.allocate(arena);
157+
long[] dims = Foo.points3$dimensions();
158+
for (int i = 0 ; i < dims[0] ; i++) {
159+
for (int j = 0; j < dims[1]; j++) {
160+
for (int k = 0; k < dims[2]; k++) {
161+
MemorySegment point = Point.allocate(arena);
162+
Point.x(point, i + j + k + 1);
163+
Point.y(point, i + j + k + 2);
164+
Foo.points3(foo, i, j, k, point);
165+
assertEquals(Point.x(Foo.points3(foo, i, j, k)), i + j + k + 1);
166+
assertEquals(Point.y(Foo.points3(foo, i, j, k)), i + j + k + 2);
167+
}
168+
}
169+
}
170+
}
171+
}
172+
173+
@Test
174+
public void testArrayAccessGlobalStruct1() {
175+
try (Arena arena = Arena.ofConfined()) {
176+
long[] dims = points1$dimensions();
177+
for (int i = 0; i < dims[0]; i++) {
178+
MemorySegment point = Point.allocate(arena);
179+
Point.x(point, i + 1);
180+
Point.y(point, i + 2);
181+
points1(i, point);
182+
assertEquals(Point.x(points1(i)), i + 1);
183+
assertEquals(Point.y(points1(i)), i + 2);
184+
}
185+
}
186+
}
187+
188+
@Test
189+
public void testArrayAccessGlobalStruct2() {
190+
try (Arena arena = Arena.ofConfined()) {
191+
long[] dims = points2$dimensions();
192+
for (int i = 0; i < dims[0]; i++) {
193+
for (int j = 0; j < dims[1]; j++) {
194+
MemorySegment point = Point.allocate(arena);
195+
Point.x(point, i + j + 1);
196+
Point.y(point, i + j + 2);
197+
points2(i, j, point);
198+
assertEquals(Point.x(points2(i, j)), i + j + 1);
199+
assertEquals(Point.y(points2(i, j)), i + j + 2);
200+
}
201+
}
202+
}
203+
}
204+
205+
@Test
206+
public void testArrayAccessGlobalStruct3() {
207+
try (Arena arena = Arena.ofConfined()) {
208+
long[] dims = points3$dimensions();
209+
for (int i = 0 ; i < dims[0] ; i++) {
210+
for (int j = 0; j < dims[1]; j++) {
211+
for (int k = 0; k < dims[2]; k++) {
212+
MemorySegment point = Point.allocate(arena);
213+
Point.x(point, i + j + k + 1);
214+
Point.y(point, i + j + k + 2);
215+
points3(i, j, k, point);
216+
assertEquals(Point.x(points3(i, j, k)), i + j + k + 1);
217+
assertEquals(Point.y(points3(i, j, k)), i + j + k + 2);
218+
}
219+
}
220+
}
221+
}
222+
}
223+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
#ifdef _WIN64
25+
#define EXPORT __declspec(dllexport)
26+
#else
27+
#define EXPORT
28+
#endif
29+
30+
struct Point {
31+
int x;
32+
int y;
33+
};
34+
35+
// array fields in struct
36+
37+
struct Foo {
38+
struct Point points1[2];
39+
struct Point points2[2][3];
40+
struct Point points3[2][3][4];
41+
42+
int ints1[2];
43+
int ints2[2][3];
44+
int ints3[2][3][4];
45+
};
46+
47+
// array global vars
48+
49+
EXPORT extern struct Point points1[2];
50+
EXPORT extern struct Point points2[2][3];
51+
EXPORT extern struct Point points3[2][3][4];
52+
53+
EXPORT extern int ints1[2];
54+
EXPORT extern int ints2[2][3];
55+
EXPORT extern int ints3[2][3][4];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
#include "array_access.h"
25+
26+
EXPORT struct Point points1[2];
27+
EXPORT struct Point points2[2][3];
28+
EXPORT struct Point points3[2][3][4];
29+
30+
EXPORT int ints1[2];
31+
EXPORT int ints2[2][3];
32+
EXPORT int ints3[2][3][4];

‎test/testng/org/openjdk/jextract/test/toolprovider/TestClassGeneration.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ public void testStructMember(String structName, MemoryLayout memberLayout, Class
171171
MemoryLayout structLayout = (MemoryLayout) layout_getter.invoke(null);
172172
try (Arena arena = Arena.ofConfined()) {
173173
MemorySegment struct = arena.allocate(structLayout);
174-
Field offsetField = findField(structCls, memberName + "$OFFSET");
175-
assertNotNull(offsetField);
176-
assertEquals(offsetField.getType(), long.class);
177-
assertEquals(offsetField.get(null), structLayout.byteOffset(PathElement.groupElement(memberName)));
174+
Method offsetMethod = findMethod(structCls, memberName + "$offset");
175+
assertNotNull(offsetMethod);
176+
assertEquals(offsetMethod.getReturnType(), long.class);
177+
assertEquals(offsetMethod.invoke(null), structLayout.byteOffset(PathElement.groupElement(memberName)));
178178

179179
Method getter = checkMethod(structCls, memberName, expectedType, MemorySegment.class);
180180
Method setter = checkMethod(structCls, memberName, void.class, MemorySegment.class, expectedType);

‎test/testng/org/openjdk/jextract/test/toolprovider/docComments/TestDocComments.java

+18-4
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,27 @@ public void testTypedefs() throws IOException {
7878
@Test
7979
public void testArrays() throws IOException {
8080
var comments = getDocComments("arrays.h", "arrays_h.java");
81-
assertEquals(comments, List.of(
81+
assertContains(comments, List.of(
8282
"Getter for variable: int abc[10]",
83+
"Indexed getter for variable: int abc[10]",
8384
"Setter for variable: int abc[10]",
85+
"Indexed setter for variable: int abc[10]",
8486
"Getter for variable: float numbers[3]",
87+
"Indexed getter for variable: float numbers[3]",
8588
"Setter for variable: float numbers[3]",
89+
"Indexed setter for variable: float numbers[3]",
8690
"Getter for variable: char *msg[5]",
91+
"Indexed getter for variable: char *msg[5]",
8792
"Setter for variable: char *msg[5]",
93+
"Indexed setter for variable: char *msg[5]",
8894
"Getter for variable: int pixels[200][100]",
95+
"Indexed getter for variable: int pixels[200][100]",
8996
"Setter for variable: int pixels[200][100]",
97+
"Indexed setter for variable: int pixels[200][100]",
9098
"Getter for variable: int points[10][20][30]",
91-
"Setter for variable: int points[10][20][30]"));
99+
"Indexed getter for variable: int points[10][20][30]",
100+
"Setter for variable: int points[10][20][30]",
101+
"Indexed setter for variable: int points[10][20][30]"));
92102
}
93103

94104
@Test
@@ -137,11 +147,15 @@ public void testFunctionPointer4() throws IOException {
137147
@Test
138148
public void testVariables() throws IOException {
139149
var comments = getDocComments("variables.h", "variables_h.java");
140-
assertEquals(comments, List.of(
150+
assertContains(comments, List.of(
141151
"Getter for variable: int abc",
142152
"Setter for variable: int abc",
153+
"Layout for variable: int abc",
154+
"Segment for variable: int abc",
143155
"Getter for variable: char *msg",
144-
"Setter for variable: char *msg"
156+
"Setter for variable: char *msg",
157+
"Layout for variable: char *msg",
158+
"Segment for variable: char *msg"
145159
));
146160
}
147161

0 commit comments

Comments
 (0)
Please sign in to comment.