From 7addd90bf98e5677cb7184ffe99b36b963493aef Mon Sep 17 00:00:00 2001 From: Jan-Willem Harmannij Date: Sat, 28 Dec 2024 11:57:21 +0100 Subject: [PATCH] Generate a correct memory layout and accessors for fields containing a `GList`/`GSList` (fixes #173) --- .../java/io/github/jwharm/javagi/JavaGI.java | 4 +-- .../generators/TypedValueGenerator.java | 8 +++++ .../io/github/jwharm/javagi/gir/Alias.java | 13 +++---- .../jwharm/javagi/gir/RegisteredType.java | 4 +++ .../jwharm/javagi/patches/GLibPatch.java | 2 +- .../javagi/test/gtk/PangoLayoutLineTest.java | 36 +++++++++++++++++++ 6 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 modules/gtk/src/test/java/io/github/jwharm/javagi/test/gtk/PangoLayoutLineTest.java diff --git a/generator/src/main/java/io/github/jwharm/javagi/JavaGI.java b/generator/src/main/java/io/github/jwharm/javagi/JavaGI.java index a718479e..8ff0fc83 100644 --- a/generator/src/main/java/io/github/jwharm/javagi/JavaGI.java +++ b/generator/src/main/java/io/github/jwharm/javagi/JavaGI.java @@ -270,8 +270,8 @@ public static void generate(String namespace, for (var rt : ns.registeredTypes().values()) { // Do not generate record types named "...Private" (except for - // GPrivate) - if (rt.skipJava()) + // GPrivate) or types that are custom implemented in java-gi + if (rt.skipJava() || rt.customJava()) continue; typeSpec = switch(rt) { diff --git a/generator/src/main/java/io/github/jwharm/javagi/generators/TypedValueGenerator.java b/generator/src/main/java/io/github/jwharm/javagi/generators/TypedValueGenerator.java index 93283fb1..e252392b 100644 --- a/generator/src/main/java/io/github/jwharm/javagi/generators/TypedValueGenerator.java +++ b/generator/src/main/java/io/github/jwharm/javagi/generators/TypedValueGenerator.java @@ -319,6 +319,13 @@ PartialStatement marshalNativeToJava(Type type, String identifier, boolean upcal PartialStatement elementConstructor = getElementConstructor(type, 0); PartialStatement elementDestructor = getElementDestructor(type, 0); + if ("runs".equals(v.attr("name"))) { + System.out.println("runs:"); + System.out.println(type.toString()); + System.out.println(((Type) type.anyTypes().getFirst()).lookup()); + System.out.println(elementConstructor.format()); + } + // Get parent node (parameter, return value, ...) Node parent = type.parent(); while (parent instanceof AnyType) @@ -330,6 +337,7 @@ PartialStatement marshalNativeToJava(Type type, String identifier, boolean upcal case InstanceParameter i -> i.transferOwnership(); case ReturnValue r -> r.transferOwnership(); case Property p -> p.transferOwnership(); + case Field _ -> NONE; default -> throw new IllegalStateException(); }; diff --git a/generator/src/main/java/io/github/jwharm/javagi/gir/Alias.java b/generator/src/main/java/io/github/jwharm/javagi/gir/Alias.java index bb29dc98..04ad5f23 100644 --- a/generator/src/main/java/io/github/jwharm/javagi/gir/Alias.java +++ b/generator/src/main/java/io/github/jwharm/javagi/gir/Alias.java @@ -19,12 +19,10 @@ package io.github.jwharm.javagi.gir; -import com.squareup.javapoet.TypeName; import io.github.jwharm.javagi.util.PartialStatement; import static io.github.jwharm.javagi.util.CollectionUtils.*; -import java.lang.foreign.MemorySegment; import java.util.List; import java.util.Map; import java.util.Objects; @@ -67,12 +65,11 @@ public RegisteredType lookup() { return null; } - @Override - public PartialStatement constructorName() { - RegisteredType target = lookup(); - return target == null ? null : target.constructorName(); - } - + /** + * An Alias must be destroyed with the appropriate free-func from the + * target type. So {@link RegisteredType#destructorName} is overridden + * to refer to the target type. + */ @Override public PartialStatement destructorName() { RegisteredType target = lookup(); diff --git a/generator/src/main/java/io/github/jwharm/javagi/gir/RegisteredType.java b/generator/src/main/java/io/github/jwharm/javagi/gir/RegisteredType.java index a1913d90..1eaa1e4d 100644 --- a/generator/src/main/java/io/github/jwharm/javagi/gir/RegisteredType.java +++ b/generator/src/main/java/io/github/jwharm/javagi/gir/RegisteredType.java @@ -134,4 +134,8 @@ default String getTypeFunc() { default boolean skipJava() { return attrBool("java-gi-skip", false); } + + default boolean customJava() { + return attrBool("java-gi-custom", false); + } } diff --git a/generator/src/main/java/io/github/jwharm/javagi/patches/GLibPatch.java b/generator/src/main/java/io/github/jwharm/javagi/patches/GLibPatch.java index 5495f15d..f2c0761f 100644 --- a/generator/src/main/java/io/github/jwharm/javagi/patches/GLibPatch.java +++ b/generator/src/main/java/io/github/jwharm/javagi/patches/GLibPatch.java @@ -140,7 +140,7 @@ public GirElement patch(GirElement element, String namespace) { if (element instanceof Record r && List.of("ByteArray", "HashTable", "List", "SList") .contains(r.name())) - return r.withAttribute("java-gi-skip", "1"); + return r.withAttribute("java-gi-custom", "1"); return element; } diff --git a/modules/gtk/src/test/java/io/github/jwharm/javagi/test/gtk/PangoLayoutLineTest.java b/modules/gtk/src/test/java/io/github/jwharm/javagi/test/gtk/PangoLayoutLineTest.java new file mode 100644 index 00000000..a2d21e14 --- /dev/null +++ b/modules/gtk/src/test/java/io/github/jwharm/javagi/test/gtk/PangoLayoutLineTest.java @@ -0,0 +1,36 @@ +package io.github.jwharm.javagi.test.gtk; + +import org.gnome.glib.SList; +import org.gnome.gtk.Gtk; +import org.gnome.gtk.Label; +import org.gnome.pango.Context; +import org.gnome.pango.Layout; +import org.gnome.pango.LayoutLine; +import org.gnome.pango.LayoutRun; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Test reading an {@link SList} from a field. + */ +public class PangoLayoutLineTest { + + @Test + public void testPangoLayoutLine() { + Gtk.init(); + + String TEST_STR = "test"; + int TEST_LENGTH = TEST_STR.length(); + + Label label = new Label(); + Context context = label.getPangoContext(); + Layout layout = new Layout(context); + layout.setText(TEST_STR, TEST_LENGTH); + SList lines = layout.getLinesReadonly(); + LayoutLine line = lines.getFirst(); + SList runs = line.readRuns(); + LayoutRun run = runs.getFirst(); + assertEquals(TEST_LENGTH, run.readItem().readNumChars()); + } +}