Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jextract-swift support Swift properties as Java get/set method pairs #24

Closed
DougGregor opened this issue Sep 30, 2024 · 3 comments · Fixed by #41
Closed

jextract-swift support Swift properties as Java get/set method pairs #24

DougGregor opened this issue Sep 30, 2024 · 3 comments · Fixed by #41
Assignees
Labels
jextract-swift Issues related to jextract-swift

Comments

@DougGregor
Copy link
Member

jextract-swift currently ignores public Swift properties when creating Java wrappers for the Swift type. We could instead produce wrappers for the getter/setter. For example, given something like:

public class MySwiftClass {
  public var counter: Int32
}

the Java class could have:

public int getCounter();
public void setCounter(int newValue);

that call the getter/setter, respectively.

@ktoso
Copy link
Collaborator

ktoso commented Oct 1, 2024

Interestingly the JDK's jextract doesn't follow setter/getter style anymore. It does counter() / counter(int) which feels a bit more modern-Java tbh, so the method names could be debated.

Implementation notes:

To follow the general jextract style we should emit something as follows:

    // --------------------------------------------------------------------------------------------------------
    // ==== len

    private static final OfLong len$LAYOUT = (OfLong)$LAYOUT.select(groupElement("len"));

    private static class len$property {
        public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of(
                /* -> */ManualJavaKitExample.SWIFT_INT,
                /* self = */ ManualJavaKitExample.SWIFT_POINTER
        );
        public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid(
                /* self = */ ManualJavaKitExample.SWIFT_POINTER,
                ManualJavaKitExample.SWIFT_INT
        );

        private static final String BASE_NAME = "$s14JavaKitExample12MySwiftClassC3lenSiv";
        public static final MemorySegment ADDR_GET = ManualJavaKitExample.findOrThrow(BASE_NAME + "g");
        public static final MemorySegment ADDR_SET = ManualJavaKitExample.findOrThrow(BASE_NAME + "s");

        public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET);
        public static final MethodHandle HANDLE_SET = Linker.nativeLinker().downcallHandle(ADDR_SET, DESC_SET);
    }

    public static final OfLong len$layout() {
        return len$LAYOUT;
    }

    private static final long len$OFFSET = 8; // FIXME: we don't know yet

    public static final long len$offset() {
        return len$OFFSET;
    }

    public static FunctionDescriptor len$get$descriptor() {
        return len$property.DESC_GET;
    }
    public static MethodHandle len$get$handle() {
        return len$property.HANDLE_GET;
    }
    public static MemorySegment len$get$address() {
        return len$property.ADDR_GET;
    }

    public static long getLen(MemorySegment self) {
        var mh$ = len$property.HANDLE_GET;
        try {
            if (TRACE_DOWNCALLS) {
                traceDowncall("len$getter", self);
            }
            return (long) mh$.invokeExact(self);
        } catch (Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }

    public static void getLen$direct(MemorySegment self) {
        // FIXME: we don't know the right offset yet, we need to get told in the .swiftinterface
        self.get(len$LAYOUT, len$OFFSET);
    }

    public static long getLen$direct(MemorySegment self) {
        return self.get(len$LAYOUT, len$OFFSET);
    }


    public static FunctionDescriptor len$set$descriptor() {
        return len$property.DESC_SET;
    }
    public static MethodHandle len$set$handle() {
        return len$property.HANDLE_SET;
    }
    public static MemorySegment len$set$address() {
        return len$property.ADDR_SET;
    }


    /**
     * Setter for field:
     * {@snippet lang = Swift :
     * var len: Int { set }
     * }
     */
    public static void setLen(MemorySegment self, long fieldValue) {
        var mh$ = len$property.HANDLE_SET;
        try {
            if (TRACE_DOWNCALLS) {
                traceDowncall("len$setter", self, fieldValue);
            }
            mh$.invokeExact(self, fieldValue);
        } catch (Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    public static void setLen$direct(MemorySegment self, long fieldValue) {
        // FIXME: we don't know the right offset yet, we need to get told in the .swiftinterface
        self.set(len$LAYOUT, len$OFFSET, fieldValue);
    }

^ parts of this snippet don't matter for this "accessors only" approach or may be slightly incorrect, but that's the general shape.

We can't properly do the getLen$direct() / setLen$direct() yet, and it's probably a separate task to do these -- it'd depend on layout information of Swift and can only be used safely if a Swift field has no side effects (like willSet).

For this task, we should focus on calling the accessors, and we can do the direct access over here: #30

@ktoso ktoso changed the title Expose Swift properties as Java get/set method pairs jextract-swift: Support Swift properties as Java get/set method pairs Oct 1, 2024
@ktoso ktoso changed the title jextract-swift: Support Swift properties as Java get/set method pairs jextract-swift support Swift properties as Java get/set method pairs Oct 1, 2024
@ktoso ktoso closed this as completed in #41 Oct 8, 2024
@ktoso ktoso reopened this Oct 8, 2024
@ktoso
Copy link
Collaborator

ktoso commented Oct 8, 2024

Still some work to be done, but I'll do it in smaller follow up PRs 👍

@ktoso ktoso self-assigned this Oct 10, 2024
@ktoso
Copy link
Collaborator

ktoso commented Oct 10, 2024

Actually, let me close this as we do have get/set pair. Followups can be separate

@ktoso ktoso closed this as completed Oct 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
jextract-swift Issues related to jextract-swift
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants