From f9ae3429fc1c78eb5d6929ee5536d71ef9de3890 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 4 Jun 2025 11:03:41 -0700 Subject: [PATCH] [JExtract] Fix methods returning imported type E.g. func createMyClass(arg: Int) -> MyClass The actual downcall was not printed. --- .../com/example/swift/HelloJava2Swift.java | 3 ++ ...2JavaTranslator+JavaBindingsPrinting.swift | 8 ++-- .../MethodImportTests.swift | 48 +++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index f94a2abb..56ac4d21 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -62,6 +62,9 @@ static void examples() { obj.voidMethod(); obj.takeIntMethod(42); + MySwiftClass otherObj = MySwiftClass.factory(12, 42, arena); + otherObj.voidMethod(); + MySwiftStruct swiftValue = new MySwiftStruct(2222, 1111, arena); SwiftKit.trace("swiftValue.capacity = " + swiftValue.getCapacity()); } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift index 15fd56e3..f96d3904 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift @@ -259,11 +259,13 @@ extension Swift2JavaTranslator { } else if decl.translatedSignature.result.javaResultType == .void { printer.print("\(downCall);") } else { - let placeholder = if decl.translatedSignature.result.outParameters.isEmpty { - downCall + let placeholder: String + if decl.translatedSignature.result.outParameters.isEmpty { + placeholder = downCall } else { // FIXME: Support cdecl thunk returning a value while populating the out parameters. - "_result" + printer.print("\(downCall);") + placeholder = "_result" } let result = decl.translatedSignature.result.conversion.render(&printer, placeholder) diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 3cb69808..34fda1d4 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -33,6 +33,8 @@ final class MethodImportTests { public func globalTakeInt(i: Int) public func globalTakeIntLongString(i32: Int32, l: Int64, s: String) + + public func globalReturnClass() -> MySwiftClass extension MySwiftClass { public func helloMemberInExtension() @@ -183,6 +185,52 @@ final class MethodImportTests { ) } + @Test("Import: public func globalReturnClass() -> MySwiftClass") + func func_globalReturnClass() throws { + let st = Swift2JavaTranslator( + javaPackage: "com.example.swift", + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .error + + try st.analyze(file: "Fake.swift", text: class_interfaceFile) + + let funcDecl = st.importedGlobalFuncs.first { + $0.name == "globalReturnClass" + }! + + let output = CodePrinter.toString { printer in + st.printFuncDowncallMethod(&printer, funcDecl) + } + + assertOutput( + dump: true, + output, + expected: + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func globalReturnClass() -> MySwiftClass + * } + */ + public static MySwiftClass globalReturnClass(SwiftArena swiftArena$) { + var mh$ = swiftjava___FakeModule_globalReturnClass.HANDLE; + try { + MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(_result); + } + mh$.invokeExact(_result); + return new MySwiftClass(_result, swiftArena$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """ + ) + } + @Test func method_class_helloMemberFunction() throws { let st = Swift2JavaTranslator(