From 99d52279d7d02b5854863418eeb3c079bfb73f95 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Fri, 3 Apr 2026 17:36:10 +0900
Subject: [PATCH 01/17] Generate foundation types in SwiftKitCore
---
.../test/java/com/example/swift/DataTest.java | 1 +
Sources/FakeFoundation/Data.swift | 26 ++++
Sources/FakeFoundation/DataProtocol.swift | 21 +++
Sources/FakeFoundation/Date.swift | 27 ++++
...t2JavaGenerator+JavaBindingsPrinting.swift | 2 +-
...ISwift2JavaGenerator+JavaTranslation.swift | 53 +++++--
.../JavaTypes/JavaType+JDK.swift | 11 ++
.../Swift2JavaTranslator.swift | 2 +-
.../generated/Data+SwiftJava.swift | 55 ++++++++
.../generated/DataProtocol+SwiftJava.swift | 19 +++
.../generated/Date+SwiftJava.swift | 53 +++++++
.../generated/SwiftJavaModule+SwiftJava.swift | 12 ++
.../swift/swiftkit/core/generated/Data.java | 133 ++++++++++++++++++
.../swiftkit/core/generated/DataProtocol.java | 14 ++
.../swift/swiftkit/core/generated/Date.java | 131 +++++++++++++++++
.../swiftkit/core/generated/SwiftJava.java | 20 +++
scripts/swiftkit-jni-generate-bindings.sh | 50 +++++++
17 files changed, 616 insertions(+), 14 deletions(-)
create mode 100644 Sources/FakeFoundation/Data.swift
create mode 100644 Sources/FakeFoundation/DataProtocol.swift
create mode 100644 Sources/FakeFoundation/Date.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java
create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java
create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
create mode 100755 scripts/swiftkit-jni-generate-bindings.sh
diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
index a6024ca12..d947e7133 100644
--- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
+++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
@@ -16,6 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
+import org.swift.swiftkit.core.generated.Data;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/Sources/FakeFoundation/Data.swift b/Sources/FakeFoundation/Data.swift
new file mode 100644
index 000000000..5fd160dd0
--- /dev/null
+++ b/Sources/FakeFoundation/Data.swift
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public struct Data: DataProtocol {
+ public init(bytes: UnsafeRawPointer, count: Int)
+ public init(_ bytes: [UInt8])
+ public var count: Int { get }
+ public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
+}
diff --git a/Sources/FakeFoundation/DataProtocol.swift b/Sources/FakeFoundation/DataProtocol.swift
new file mode 100644
index 000000000..d5a02d423
--- /dev/null
+++ b/Sources/FakeFoundation/DataProtocol.swift
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public protocol DataProtocol {}
diff --git a/Sources/FakeFoundation/Date.swift b/Sources/FakeFoundation/Date.swift
new file mode 100644
index 000000000..ee18b8afc
--- /dev/null
+++ b/Sources/FakeFoundation/Date.swift
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public struct Date {
+ /// The interval between the date object and 00:00:00 UTC on 1 January 1970.
+ public var timeIntervalSince1970: Double { get }
+
+ /// Returns a `Date` initialized relative to 00:00:00 UTC on 1 January 1970 by a given number of seconds.
+ public init(timeIntervalSince1970: Double)
+}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
index 8f6d97a67..4581091b8 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -616,7 +616,7 @@ extension JNISwift2JavaGenerator {
}
generics.append((name, extends))
}
- .map { "\($0) extends \($1.compactMap(\.className).joined(separator: " & "))" }
+ .map { "\($0) extends \($1.compactMap(\.description).joined(separator: " & "))" }
.joined(separator: ", ")
if !generics.isEmpty {
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
index 69455ba69..8df7930f6 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
@@ -505,10 +505,24 @@ extension JNISwift2JavaGenerator {
)
case .foundationDate, .essentialsDate:
- break // Handled as wrapped struct
+ return TranslatedParameter(
+ parameter: JavaParameter(
+ name: parameterName,
+ type: .concrete(.swiftkitCoreGeneratedDate),
+ annotations: parameterAnnotations,
+ ),
+ conversion: .valueMemoryAddress(.placeholder),
+ )
case .foundationData, .essentialsData:
- break // Handled as wrapped struct
+ return TranslatedParameter(
+ parameter: JavaParameter(
+ name: parameterName,
+ type: .concrete(.swiftkitCoreGeneratedData),
+ annotations: parameterAnnotations,
+ ),
+ conversion: .valueMemoryAddress(.placeholder),
+ )
case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer:
return TranslatedParameter(
@@ -945,12 +959,22 @@ extension JNISwift2JavaGenerator {
)
case .foundationDate, .essentialsDate:
- // Handled as wrapped struct
- break
+ let javaType = JavaType.swiftkitCoreGeneratedDate
+ return TranslatedResult(
+ javaType: javaType,
+ annotations: resultAnnotations,
+ outParameters: [],
+ conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType),
+ )
case .foundationData, .essentialsData:
- // Handled as wrapped struct
- break
+ let javaType = JavaType.swiftkitCoreGeneratedData
+ return TranslatedResult(
+ javaType: javaType,
+ annotations: resultAnnotations,
+ outParameters: [],
+ conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType),
+ )
case .foundationUUID, .essentialsUUID:
return TranslatedResult(
@@ -1094,13 +1118,13 @@ extension JNISwift2JavaGenerator {
return .swiftSet(elementJavaType)
case .foundationDate, .essentialsDate:
- return .class(package: nil, name: "Date")
+ return .swiftkitCoreGeneratedDate
case .foundationData, .essentialsData:
- return .class(package: nil, name: "Data")
+ return .swiftkitCoreGeneratedData
case .foundationDataProtocol, .essentialsDataProtocol:
- return .class(package: nil, name: "DataProtocol")
+ return .swiftkitCoreGeneratedDataProtocol
case .foundationUUID, .essentialsUUID:
return .javaUtilUUID
@@ -1162,7 +1186,6 @@ extension JNISwift2JavaGenerator {
genericParameters: [SwiftGenericParameterDeclaration],
genericRequirements: [SwiftGenericRequirement],
) throws -> TranslatedResult {
- let arity = elements.count
var outParameters: [OutParameter] = []
var elementOutParamNames: [String] = []
var elementConversions: [JavaNativeConversionStep] = []
@@ -1854,16 +1877,22 @@ extension JNISwift2JavaGenerator {
case .wrapMemoryAddressUnsafe(let inner, let javaType):
let inner = inner.render(&printer, placeholder)
- guard case .class(_, let className, let typeParameters) = javaType else {
+ guard case .class(let package, let className, let typeParameters) = javaType else {
fatalError("\(javaType) is not class.")
}
+ let packagePart: String =
+ if let package {
+ "\(package)."
+ } else {
+ ""
+ }
let genericClause =
if !typeParameters.isEmpty {
"<\(typeParameters.map(\.description).joined(separator: ", "))>"
} else {
""
}
- return "\(className).\(genericClause)wrapMemoryAddressUnsafe(\(inner), swiftArena)"
+ return "\(packagePart)\(className).\(genericClause)wrapMemoryAddressUnsafe(\(inner), swiftArena)"
case .constructJavaClass(let inner, let javaType):
let inner = inner.render(&printer, placeholder)
diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
index 34cb7f458..56a6d65bf 100644
--- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
+++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
@@ -59,4 +59,15 @@ extension JavaType {
.class(package: "java.util", name: "UUID")
}
+ static var swiftkitCoreGeneratedDate: JavaType {
+ .class(package: "org.swift.swiftkit.core.generated", name: "Date")
+ }
+
+ static var swiftkitCoreGeneratedData: JavaType {
+ .class(package: "org.swift.swiftkit.core.generated", name: "Data")
+ }
+
+ static var swiftkitCoreGeneratedDataProtocol: JavaType {
+ .class(package: "org.swift.swiftkit.core.generated", name: "DataProtocol")
+ }
}
diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
index a5d96a1af..d9952724c 100644
--- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
+++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
@@ -111,7 +111,7 @@ extension Swift2JavaTranslator {
// Apply any specializations registered after their target types were visited
visitor.applyPendingSpecializations()
- self.visitFoundationDeclsIfNeeded(with: visitor)
+// self.visitFoundationDeclsIfNeeded(with: visitor)
}
private func visitFoundationDeclsIfNeeded(with visitor: Swift2JavaVisitor) {
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
new file mode 100644
index 000000000..dbe1a8f05
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
@@ -0,0 +1,55 @@
+
+// ==== --------------------------------------------------
+// Thunks for Data
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_Data {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
+
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024init___3B")
+public func Java_org_swift_swiftkit_core_generated_Data__00024init___3B(environment: UnsafeMutablePointer!, thisClass: jclass, bytes: jbyteArray?) -> jlong {
+ let result$ = UnsafeMutablePointer.allocate(capacity: 1)
+ result$.initialize(to: Data.init([UInt8](fromJNI: bytes, in: environment)))
+ let resultBits$ = Int64(Int(bitPattern: result$))
+ return resultBits$.getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024getCount__J")
+public func Java_org_swift_swiftkit_core_generated_Data__00024getCount__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong {
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: environment))
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$)
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return Int64(selfPointer$.pointee.count).getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024typeMetadataAddressDowncall__")
+public func Java_org_swift_swiftkit_core_generated_Data__00024typeMetadataAddressDowncall__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
+ let metadataPointer = unsafeBitCast(Data.self, to: UnsafeRawPointer.self)
+ return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
new file mode 100644
index 000000000..3f7754f5e
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
@@ -0,0 +1,19 @@
+
+// ==== --------------------------------------------------
+// Thunks for DataProtocol
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_DataProtocol {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
+
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
new file mode 100644
index 000000000..838d8729e
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
@@ -0,0 +1,53 @@
+
+// ==== --------------------------------------------------
+// Thunks for Date
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_Date {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024init__D")
+public func Java_org_swift_swiftkit_core_generated_Date__00024init__D(environment: UnsafeMutablePointer!, thisClass: jclass, timeIntervalSince1970: jdouble) -> jlong {
+ let result$ = UnsafeMutablePointer.allocate(capacity: 1)
+ result$.initialize(to: Date.init(timeIntervalSince1970: Double(fromJNI: timeIntervalSince1970, in: environment)))
+ let resultBits$ = Int64(Int(bitPattern: result$))
+ return resultBits$.getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024getTimeIntervalSince1970__J")
+public func Java_org_swift_swiftkit_core_generated_Date__00024getTimeIntervalSince1970__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jdouble {
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: environment))
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$)
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return selfPointer$.pointee.timeIntervalSince1970.getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024typeMetadataAddressDowncall__")
+public func Java_org_swift_swiftkit_core_generated_Date__00024typeMetadataAddressDowncall__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
+ let metadataPointer = unsafeBitCast(Date.self, to: UnsafeRawPointer.self)
+ return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
new file mode 100644
index 000000000..e24e89ffe
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
@@ -0,0 +1,12 @@
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java
new file mode 100644
index 000000000..c6b0f3636
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java
@@ -0,0 +1,133 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+package org.swift.swiftkit.core.generated;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.core.collections.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.swift.swiftkit.core.annotations.*;
+
+public final class Data implements JNISwiftInstance, DataProtocol {
+ static final String LIB_NAME = "SwiftJava";
+
+ @SuppressWarnings("unused")
+ private static final boolean INITIALIZED_LIBS = initializeLibs();
+ static boolean initializeLibs() {
+ System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ System.loadLibrary(LIB_NAME);
+ return true;
+ }
+ /**
+ * The designated constructor of any imported Swift types.
+ *
+ * @param selfPointer a pointer to the memory containing the value
+ * @param swiftArena the arena this object belongs to. When the arena goes out of scope, this value is destroyed.
+ */
+ private Data(long selfPointer, SwiftArena swiftArena) {
+ SwiftObjects.requireNonZero(selfPointer, "selfPointer");
+ this.selfPointer = selfPointer;
+
+ // Only register once we have fully initialized the object since this will need the object pointer.
+ swiftArena.register(this);
+ } // printConcreteType(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:230
+
+ /**
+ * Assume that the passed {@code long} represents a memory address of a {@link Data}.
+ *
+ * Warnings:
+ *
+ * - No checks are performed about the compatibility of the pointed at memory and the actual Data types.
+ * - This operation does not copy, or retain, the pointed at pointer, so its lifetime must be ensured manually to be valid when wrapping.
+ *
+ */
+ public static Data wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
+ return new Data(selfPointer, swiftArena);
+ }
+
+ public static Data wrapMemoryAddressUnsafe(long selfPointer) {
+ return new Data(selfPointer, SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA);
+ }
+ /** Pointer to the "self". */
+ private final long selfPointer;
+
+ /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */
+ private final AtomicBoolean $state$destroyed = new AtomicBoolean(false);
+
+ public long $memoryAddress() {
+ return this.selfPointer;
+ }
+
+ @Override
+ public AtomicBoolean $statusDestroyedFlag() {
+ return $state$destroyed;
+ }
+
+
+
+ // ==== --------------------------------------------------
+ // Data.init
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public init(_ bytes: [UInt8])
+ * }
+ */
+ public static Data init(@Unsigned byte[] bytes, SwiftArena swiftArena) {
+ return Data.wrapMemoryAddressUnsafe(Data.$init(Objects.requireNonNull(bytes, "bytes must not be null")), swiftArena);
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ private static native long $init(byte[] bytes);
+
+
+
+ // ==== --------------------------------------------------
+ // getter:Data.count
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public var count: Int
+ * }
+ */
+ public long getCount() {
+ return Data.$getCount(this.$memoryAddress());
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ private static native long $getCount(long selfPointer);
+
+ private static native long $typeMetadataAddressDowncall();
+ @Override
+ public long $typeMetadataAddress() {
+ return Data.$typeMetadataAddressDowncall();
+ } // printTypeMetadataAddressFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:776
+
+ public String toString() {
+ return SwiftObjects.toString(this.$memoryAddress(), this.$typeMetadataAddress());
+ }
+
+ public String toDebugString() {
+ return SwiftObjects.toDebugString(this.$memoryAddress(), this.$typeMetadataAddress());
+ }
+
+ @Override
+ public Runnable $createDestroyFunction() {
+ long self$ = this.$memoryAddress();
+ long selfType$ = this.$typeMetadataAddress();
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall("Data.$createDestroyFunction",
+ "this", this,
+ "self", self$);
+ }
+ return new Runnable() {
+ @Override
+ public void run() {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall("Data.$destroy", "self", self$);
+ }
+ SwiftObjects.destroy(self$, selfType$);
+ }
+ };
+ } // printDestroyFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:790
+} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:402
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
new file mode 100644
index 000000000..8e9c0b90f
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
@@ -0,0 +1,14 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+package org.swift.swiftkit.core.generated;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.core.collections.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.swift.swiftkit.core.annotations.*;
+
+public interface DataProtocol extends JNISwiftInstance {
+} // printProtocol(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:154
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java
new file mode 100644
index 000000000..1e32774b5
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java
@@ -0,0 +1,131 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+package org.swift.swiftkit.core.generated;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.core.collections.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.swift.swiftkit.core.annotations.*;
+
+public final class Date implements JNISwiftInstance {
+ static final String LIB_NAME = "SwiftJava";
+
+ @SuppressWarnings("unused")
+ private static final boolean INITIALIZED_LIBS = initializeLibs();
+ static boolean initializeLibs() {
+ System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ System.loadLibrary(LIB_NAME);
+ return true;
+ }
+ /**
+ * The designated constructor of any imported Swift types.
+ *
+ * @param selfPointer a pointer to the memory containing the value
+ * @param swiftArena the arena this object belongs to. When the arena goes out of scope, this value is destroyed.
+ */
+ private Date(long selfPointer, SwiftArena swiftArena) {
+ SwiftObjects.requireNonZero(selfPointer, "selfPointer");
+ this.selfPointer = selfPointer;
+
+ // Only register once we have fully initialized the object since this will need the object pointer.
+ swiftArena.register(this);
+ } // printConcreteType(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:230
+
+ /**
+ * Assume that the passed {@code long} represents a memory address of a {@link Date}.
+ *
+ * Warnings:
+ *
+ * - No checks are performed about the compatibility of the pointed at memory and the actual Date types.
+ * - This operation does not copy, or retain, the pointed at pointer, so its lifetime must be ensured manually to be valid when wrapping.
+ *
+ */
+ public static Date wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
+ return new Date(selfPointer, swiftArena);
+ }
+
+ public static Date wrapMemoryAddressUnsafe(long selfPointer) {
+ return new Date(selfPointer, SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA);
+ }
+ /** Pointer to the "self". */
+ private final long selfPointer;
+
+ /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */
+ private final AtomicBoolean $state$destroyed = new AtomicBoolean(false);
+
+ public long $memoryAddress() {
+ return this.selfPointer;
+ }
+
+ @Override
+ public AtomicBoolean $statusDestroyedFlag() {
+ return $state$destroyed;
+ }
+
+
+ // ==== --------------------------------------------------
+ // Date.init
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public init(timeIntervalSince1970: Double)
+ * }
+ */
+ public static Date init(double timeIntervalSince1970, SwiftArena swiftArena) {
+ return Date.wrapMemoryAddressUnsafe(Date.$init(timeIntervalSince1970), swiftArena);
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ private static native long $init(double timeIntervalSince1970);
+
+
+ // ==== --------------------------------------------------
+ // getter:Date.timeIntervalSince1970
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public var timeIntervalSince1970: Double
+ * }
+ */
+ public double getTimeIntervalSince1970() {
+ return Date.$getTimeIntervalSince1970(this.$memoryAddress());
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ private static native double $getTimeIntervalSince1970(long selfPointer);
+
+ private static native long $typeMetadataAddressDowncall();
+ @Override
+ public long $typeMetadataAddress() {
+ return Date.$typeMetadataAddressDowncall();
+ } // printTypeMetadataAddressFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:776
+
+ public String toString() {
+ return SwiftObjects.toString(this.$memoryAddress(), this.$typeMetadataAddress());
+ }
+
+ public String toDebugString() {
+ return SwiftObjects.toDebugString(this.$memoryAddress(), this.$typeMetadataAddress());
+ }
+
+ @Override
+ public Runnable $createDestroyFunction() {
+ long self$ = this.$memoryAddress();
+ long selfType$ = this.$typeMetadataAddress();
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall("Date.$createDestroyFunction",
+ "this", this,
+ "self", self$);
+ }
+ return new Runnable() {
+ @Override
+ public void run() {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall("Date.$destroy", "self", self$);
+ }
+ SwiftObjects.destroy(self$, selfType$);
+ }
+ };
+ } // printDestroyFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:790
+} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:402
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
new file mode 100644
index 000000000..0a19e273c
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
@@ -0,0 +1,20 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+package org.swift.swiftkit.core.generated;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.core.collections.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.swift.swiftkit.core.annotations.*;
+
+public final class SwiftJava {
+ static final String LIB_NAME = "SwiftJava";
+
+ static {
+ System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ System.loadLibrary(LIB_NAME);
+ }
+} // printModuleClass(_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:410
diff --git a/scripts/swiftkit-jni-generate-bindings.sh b/scripts/swiftkit-jni-generate-bindings.sh
new file mode 100755
index 000000000..a83e97309
--- /dev/null
+++ b/scripts/swiftkit-jni-generate-bindings.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+##===----------------------------------------------------------------------===##
+##
+## This source file is part of the Swift.org open source project
+##
+## Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+## Licensed under Apache License v2.0
+##
+## See LICENSE.txt for license information
+## See CONTRIBUTORS.txt for the list of Swift.org project authors
+##
+## SPDX-License-Identifier: Apache-2.0
+##
+##===----------------------------------------------------------------------===##
+
+# Regenerate FFM bindings for types in SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/
+#
+# Run from the swift-java repository root:
+# ./scripts/swiftkit-ffm-generate-bindings.sh
+
+set -euo pipefail
+
+REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
+
+JAVA_OUTPUT="${REPO_ROOT}/SwiftKitCore/src/main/java"
+JAVA_PACKAGE="org.swift.swiftkit.core.generated"
+
+# Declare types to generate: SWIFT_MODULE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
+TYPES=(
+ "SwiftJava Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/generated"
+)
+
+for entry in "${TYPES[@]}"; do
+ read -r MODULE INPUT_SWIFT OUTPUT_SWIFT <<< "$entry"
+
+ echo "==> Generating ${INPUT_SWIFT}..."
+
+ xcrun swift run swift-java jextract \
+ --mode jni \
+ --swift-module "$MODULE" \
+ --input-swift "${REPO_ROOT}/${INPUT_SWIFT}" \
+ --output-swift "${REPO_ROOT}/${OUTPUT_SWIFT}" \
+ --output-java "$JAVA_OUTPUT" \
+ --java-package "$JAVA_PACKAGE"
+
+ echo " Swift thunks: ${OUTPUT_SWIFT}/"
+ echo " Java output: SwiftKitCore/src/main/java/$(echo "$JAVA_PACKAGE" | tr '.' '/')/"
+done
+
+echo "==> Done."
From cbd55ffc1a5bbd31b84b5103908d2c3516925448 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Fri, 3 Apr 2026 17:53:02 +0900
Subject: [PATCH 02/17] Add Date and Date wrapper by hand
---
.../test/java/com/example/swift/DataTest.java | 2 +-
Sources/FakeFoundation/Data.swift | 26 ----
Sources/FakeFoundation/Date.swift | 27 ----
...t2JavaGenerator+JavaBindingsPrinting.swift | 131 ------------------
...ISwift2JavaGenerator+JavaTranslation.swift | 14 +-
.../JavaTypes/JavaType+JDK.swift | 12 +-
.../Swift2JavaTranslator.swift | 33 -----
.../SwiftJavaMacros/ImplementsJavaMacro.swift | 2 +-
.../Foundation/Data+JNI.swift | 67 +++++++++
.../Foundation/Date+JNI.swift | 47 +++++++
.../generated/Data+SwiftJava.swift | 55 --------
.../generated/DataProtocol+SwiftJava.swift | 19 ---
.../generated/Date+SwiftJava.swift | 53 -------
.../generated/SwiftJavaModule+SwiftJava.swift | 12 --
.../core/{generated => foundation}/Data.java | 115 ++++++++++-----
.../core/foundation/DataProtocol.java | 11 +-
.../core/{generated => foundation}/Date.java | 109 +++++++++++----
.../swiftkit/core/generated/DataProtocol.java | 14 --
.../swiftkit/core/generated/SwiftJava.java | 20 ---
19 files changed, 298 insertions(+), 471 deletions(-)
delete mode 100644 Sources/FakeFoundation/Data.swift
delete mode 100644 Sources/FakeFoundation/Date.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift
delete mode 100644 Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
delete mode 100644 Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
delete mode 100644 Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
delete mode 100644 Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
rename SwiftKitCore/src/main/java/org/swift/swiftkit/core/{generated => foundation}/Data.java (63%)
rename Sources/FakeFoundation/DataProtocol.swift => SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java (76%)
rename SwiftKitCore/src/main/java/org/swift/swiftkit/core/{generated => foundation}/Date.java (62%)
delete mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
delete mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
index d947e7133..32bd4a98b 100644
--- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
+++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
@@ -16,7 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
-import org.swift.swiftkit.core.generated.Data;
+import org.swift.swiftkit.core.foundation.Data;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/Sources/FakeFoundation/Data.swift b/Sources/FakeFoundation/Data.swift
deleted file mode 100644
index 5fd160dd0..000000000
--- a/Sources/FakeFoundation/Data.swift
+++ /dev/null
@@ -1,26 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-public struct Data: DataProtocol {
- public init(bytes: UnsafeRawPointer, count: Int)
- public init(_ bytes: [UInt8])
- public var count: Int { get }
- public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
-}
diff --git a/Sources/FakeFoundation/Date.swift b/Sources/FakeFoundation/Date.swift
deleted file mode 100644
index ee18b8afc..000000000
--- a/Sources/FakeFoundation/Date.swift
+++ /dev/null
@@ -1,27 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-public struct Date {
- /// The interval between the date object and 00:00:00 UTC on 1 January 1970.
- public var timeIntervalSince1970: Double { get }
-
- /// Returns a `Date` initialized relative to 00:00:00 UTC on 1 January 1970 by a given number of seconds.
- public init(timeIntervalSince1970: Double)
-}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
index 4581091b8..eaf34540b 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -314,8 +314,6 @@ extension JNISwift2JavaGenerator {
printer.println()
}
- printSpecificTypeHelpers(&printer, decl)
-
printTypeMetadataAddressFunction(&printer, decl)
printer.println()
@@ -336,22 +334,6 @@ extension JNISwift2JavaGenerator {
}
}
- /// Prints helpers for specific types like `Foundation.Date`
- private func printSpecificTypeHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- guard let knownType = decl.swiftNominal.knownTypeKind else { return }
-
- switch knownType {
- case .foundationDate, .essentialsDate:
- printFoundationDateHelpers(&printer, decl)
-
- case .foundationData, .essentialsData:
- printFoundationDataHelpers(&printer, decl)
-
- default:
- break
- }
- }
-
private func printHeader(_ printer: inout CodePrinter) {
printer.print(
"""
@@ -832,117 +814,4 @@ extension JNISwift2JavaGenerator {
}
}
}
-
- private func printFoundationDateHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- printer.print(
- """
- /**
- * Converts this wrapped date to a Java {@link java.time.Instant}.
- *
- * This method constructs the {@code Instant} using the underlying {@code double} value
- * representing seconds since the Unix Epoch (January 1, 1970).
- *
- *
- * @return A {@code java.time.Instant} derived from the floating-point timestamp.
- */
- public java.time.Instant toInstant() {
- long seconds = (long) this.getTimeIntervalSince1970();
- long nanos = Math.round((this.getTimeIntervalSince1970() - seconds) * 1_000_000_000);
- return java.time.Instant.ofEpochSecond(seconds, nanos);
- }
- """
- )
- printer.println()
- printer.print(
- """
- /**
- * Initializes a Swift {@code Foundation.Date} from a Java {@link java.time.Instant}.
- *
- * Warning: Precision Loss
- *
- * The input precision will be degraded.
- *
- *
- * Java's {@code Instant} stores time with nanosecond precision (9 decimal places).
- * However, this class stores time as a 64-bit floating-point value.
- *
- *
- * This leaves enough capacity for microsecond precision (approx. 6 decimal places).
- *
- *
- * Consequently, the last ~3 digits of the {@code Instant}'s nanosecond field will be
- * truncated or subjected to rounding errors during conversion.
- *
- *
- * @param instant The source timestamp to convert.
- * @return A date derived from the input instant with microsecond precision.
- */
- public static Date fromInstant(java.time.Instant instant, SwiftArena swiftArena) {
- Objects.requireNonNull(instant, "Instant cannot be null");
- double timeIntervalSince1970 = instant.getEpochSecond() + (instant.getNano() / 1_000_000_000.0);
- return Date.init(timeIntervalSince1970, swiftArena);
- }
- """
- )
- }
-
- private func printFoundationDataHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- printer.print(
- """
- /**
- * Creates a new Swift @{link Data} instance from a byte array.
- *
- * @param bytes The byte array to copy into the Data
- * @param swiftArena The arena for memory management
- * @return A new Data instance containing a copy of the bytes
- */
- public static Data fromByteArray(byte[] bytes, SwiftArena swiftArena) {
- Objects.requireNonNull(bytes, "bytes cannot be null");
- return Data.init(bytes, swiftArena);
- }
- """
- )
-
- printer.print(
- """
- /**
- * Copies the contents of this Data to a new byte array.
- *
- * This is a relatively efficient implementation, which avoids native array copies,
- * however it will still perform a copy of the data onto the JVM heap, so use this
- * only when necessary.
- *
- *
When utmost performance is necessary, you may want to investigate the FFM mode
- * of jextract which is able to map memory more efficiently.
- *
- * @return A byte array containing a copy of this Data's bytes
- */
- public byte[] toByteArray() {
- return $toByteArray(this.$memoryAddress());
- }
- """
- )
-
- printer.print(
- """
- private static native byte[] $toByteArray(long selfPointer);
-
- /**
- * Copies the contents of this Data to a new byte array.
- *
- * @deprecated Prefer using the `toByteArray` method as it is more performant.
- * This implementation uses a naive conversion path from native bytes into jbytes
- * and then copying them onto the jvm heap.
- *
- * @return A byte array containing a copy of this Data's bytes
- */
- @Deprecated(forRemoval = true)
- public byte[] toByteArrayIndirectCopy() {
- return $toByteArrayIndirectCopy(this.$memoryAddress());
- }
-
- private static native byte[] $toByteArrayIndirectCopy(long selfPointer);
- """
- )
- }
}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
index 8df7930f6..733cbac43 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
@@ -508,7 +508,7 @@ extension JNISwift2JavaGenerator {
return TranslatedParameter(
parameter: JavaParameter(
name: parameterName,
- type: .concrete(.swiftkitCoreGeneratedDate),
+ type: .concrete(.swiftkitCoreFoundationDate),
annotations: parameterAnnotations,
),
conversion: .valueMemoryAddress(.placeholder),
@@ -518,7 +518,7 @@ extension JNISwift2JavaGenerator {
return TranslatedParameter(
parameter: JavaParameter(
name: parameterName,
- type: .concrete(.swiftkitCoreGeneratedData),
+ type: .concrete(.swiftkitCoreFoundationData),
annotations: parameterAnnotations,
),
conversion: .valueMemoryAddress(.placeholder),
@@ -959,7 +959,7 @@ extension JNISwift2JavaGenerator {
)
case .foundationDate, .essentialsDate:
- let javaType = JavaType.swiftkitCoreGeneratedDate
+ let javaType = JavaType.swiftkitCoreFoundationDate
return TranslatedResult(
javaType: javaType,
annotations: resultAnnotations,
@@ -968,7 +968,7 @@ extension JNISwift2JavaGenerator {
)
case .foundationData, .essentialsData:
- let javaType = JavaType.swiftkitCoreGeneratedData
+ let javaType = JavaType.swiftkitCoreFoundationData
return TranslatedResult(
javaType: javaType,
annotations: resultAnnotations,
@@ -1118,13 +1118,13 @@ extension JNISwift2JavaGenerator {
return .swiftSet(elementJavaType)
case .foundationDate, .essentialsDate:
- return .swiftkitCoreGeneratedDate
+ return .swiftkitCoreFoundationDate
case .foundationData, .essentialsData:
- return .swiftkitCoreGeneratedData
+ return .swiftkitCoreFoundationData
case .foundationDataProtocol, .essentialsDataProtocol:
- return .swiftkitCoreGeneratedDataProtocol
+ return .swiftkitCoreFoundationDataProtocol
case .foundationUUID, .essentialsUUID:
return .javaUtilUUID
diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
index 56a6d65bf..32e01b26f 100644
--- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
+++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
@@ -59,15 +59,15 @@ extension JavaType {
.class(package: "java.util", name: "UUID")
}
- static var swiftkitCoreGeneratedDate: JavaType {
- .class(package: "org.swift.swiftkit.core.generated", name: "Date")
+ static var swiftkitCoreFoundationDate: JavaType {
+ .class(package: "org.swift.swiftkit.core.foundation", name: "Date")
}
- static var swiftkitCoreGeneratedData: JavaType {
- .class(package: "org.swift.swiftkit.core.generated", name: "Data")
+ static var swiftkitCoreFoundationData: JavaType {
+ .class(package: "org.swift.swiftkit.core.foundation", name: "Data")
}
- static var swiftkitCoreGeneratedDataProtocol: JavaType {
- .class(package: "org.swift.swiftkit.core.generated", name: "DataProtocol")
+ static var swiftkitCoreFoundationDataProtocol: JavaType {
+ .class(package: "org.swift.swiftkit.core.foundation", name: "DataProtocol")
}
}
diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
index d9952724c..51d100350 100644
--- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
+++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
@@ -110,39 +110,6 @@ extension Swift2JavaTranslator {
// Apply any specializations registered after their target types were visited
visitor.applyPendingSpecializations()
-
-// self.visitFoundationDeclsIfNeeded(with: visitor)
- }
-
- private func visitFoundationDeclsIfNeeded(with visitor: Swift2JavaVisitor) {
- // If any API uses 'Foundation.Data' or 'FoundationEssentials.Data',
- // import 'Data' as if it's declared in this module.
- if let dataDecl = self.symbolTable[.foundationData] ?? self.symbolTable[.essentialsData] {
- let dataProtocolDecl = (self.symbolTable[.foundationDataProtocol] ?? self.symbolTable[.essentialsDataProtocol])!
- if self.isUsing(where: { $0 == dataDecl || $0 == dataProtocolDecl }) {
- visitor.visit(
- nominalDecl: dataDecl.syntax!.asNominal!,
- in: nil,
- sourceFilePath: "Foundation/FAKE_FOUNDATION_DATA.swift",
- )
- visitor.visit(
- nominalDecl: dataProtocolDecl.syntax!.asNominal!,
- in: nil,
- sourceFilePath: "Foundation/FAKE_FOUNDATION_DATAPROTOCOL.swift",
- )
- }
- }
-
- // Foundation.Date
- if let dateDecl = self.symbolTable[.foundationDate] ?? self.symbolTable[.essentialsDate] {
- if self.isUsing(where: { $0 == dateDecl }) {
- visitor.visit(
- nominalDecl: dateDecl.syntax!.asNominal!,
- in: nil,
- sourceFilePath: "Foundation/FAKE_FOUNDATION_DATE.swift",
- )
- }
- }
}
package func prepareForTranslation() {
diff --git a/Sources/SwiftJavaMacros/ImplementsJavaMacro.swift b/Sources/SwiftJavaMacros/ImplementsJavaMacro.swift
index 2770a490c..bfcde7b30 100644
--- a/Sources/SwiftJavaMacros/ImplementsJavaMacro.swift
+++ b/Sources/SwiftJavaMacros/ImplementsJavaMacro.swift
@@ -213,7 +213,7 @@ extension JavaImplementationMacro: PeerMacro {
@used
#endif
@_cdecl(\(literal: cName))
- public func \(context.makeUniqueName(swiftName))(\(raw: cParameters.map{ $0.description }.joined(separator: ", ")))\(raw: cReturnType) {
+ public func \(context.makeUniqueName("\(swiftTypeName)_\(swiftName)"))(\(raw: cParameters.map{ $0.description }.joined(separator: ", ")))\(raw: cReturnType) {
\(body)
}
"""
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
new file mode 100644
index 000000000..aa391639f
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+import SwiftJava
+import SwiftJavaJNICore
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@JavaImplementation("org.swift.swiftkit.core.foundation.Data")
+extension Data {
+ @JavaMethod("$init")
+ static func _init(environment: UnsafeMutablePointer!, bytes: [UInt8]) -> Int64 {
+ let result$ = UnsafeMutablePointer.allocate(capacity: 1)
+ result$.initialize(to: Data(bytes))
+ return Int64(Int(bitPattern: result$))
+ }
+
+ @JavaMethod("$getCount")
+ static func _getCount(environment: UnsafeMutablePointer!, selfPointer: Int64) -> Int64 {
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return Int64(selfPointer$.pointee.count)
+ }
+
+ @JavaMethod("$toByteArray")
+ static func _toByteArray(environment: UnsafeMutablePointer!, selfPointer: Int64) -> [UInt8] {
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return selfPointer$.pointee.withUnsafeBytes { buffer in
+ return buffer.getJNIValue(in: environment)
+ }
+ }
+
+ @JavaMethod("$toByteArrayIndirectCopy")
+ static func _toByteArrayIndirectCopy(environment: UnsafeMutablePointer!, selfPointer: Int64) -> [UInt8] {
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return [UInt8](selfPointer$.pointee)
+ }
+
+ @JavaMethod("$typeMetadataAddressDowncall")
+ static func _typeMetadataAddressDowncall(environment: UnsafeMutablePointer!) -> Int64 {
+ let metadataPointer = unsafeBitCast(Data.self, to: UnsafeRawPointer.self)
+ return Int64(Int(bitPattern: metadataPointer))
+ }
+}
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift
new file mode 100644
index 000000000..3c27cd7af
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+import SwiftJava
+import SwiftJavaJNICore
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@JavaImplementation("org.swift.swiftkit.core.foundation.Date")
+extension Date {
+ @JavaMethod("$init")
+ static func _init(environment: UnsafeMutablePointer!, timeIntervalSince1970: Double) -> Int64 {
+ let result$ = UnsafeMutablePointer.allocate(capacity: 1)
+ result$.initialize(to: Date(timeIntervalSince1970: timeIntervalSince1970))
+ return Int64(Int(bitPattern: result$))
+ }
+
+ @JavaMethod("$getTimeIntervalSince1970")
+ static func _getTimeIntervalSince1970(environment: UnsafeMutablePointer!, selfPointer: Int64) -> Double {
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return selfPointer$.pointee.timeIntervalSince1970
+ }
+
+ @JavaMethod("$typeMetadataAddressDowncall")
+ static func _typeMetadataAddressDowncall(environment: UnsafeMutablePointer!) -> Int64 {
+ let metadataPointer = unsafeBitCast(Date.self, to: UnsafeRawPointer.self)
+ return Int64(Int(bitPattern: metadataPointer))
+ }
+}
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
deleted file mode 100644
index dbe1a8f05..000000000
--- a/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
+++ /dev/null
@@ -1,55 +0,0 @@
-
-// ==== --------------------------------------------------
-// Thunks for Data
-
-// Generated by swift-java
-
-import SwiftJava
-import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-enum _JNI_Data {
-} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
-
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024init___3B")
-public func Java_org_swift_swiftkit_core_generated_Data__00024init___3B(environment: UnsafeMutablePointer!, thisClass: jclass, bytes: jbyteArray?) -> jlong {
- let result$ = UnsafeMutablePointer.allocate(capacity: 1)
- result$.initialize(to: Data.init([UInt8](fromJNI: bytes, in: environment)))
- let resultBits$ = Int64(Int(bitPattern: result$))
- return resultBits$.getJNILocalRefValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024getCount__J")
-public func Java_org_swift_swiftkit_core_generated_Data__00024getCount__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong {
- assert(selfPointer != 0, "selfPointer memory address was null")
- let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: environment))
- let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$)
- guard let selfPointer$ else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return Int64(selfPointer$.pointee.count).getJNILocalRefValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024typeMetadataAddressDowncall__")
-public func Java_org_swift_swiftkit_core_generated_Data__00024typeMetadataAddressDowncall__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
- let metadataPointer = unsafeBitCast(Data.self, to: UnsafeRawPointer.self)
- return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
deleted file mode 100644
index 3f7754f5e..000000000
--- a/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-
-// ==== --------------------------------------------------
-// Thunks for DataProtocol
-
-// Generated by swift-java
-
-import SwiftJava
-import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-enum _JNI_DataProtocol {
-} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
-
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
deleted file mode 100644
index 838d8729e..000000000
--- a/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
+++ /dev/null
@@ -1,53 +0,0 @@
-
-// ==== --------------------------------------------------
-// Thunks for Date
-
-// Generated by swift-java
-
-import SwiftJava
-import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-enum _JNI_Date {
-} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024init__D")
-public func Java_org_swift_swiftkit_core_generated_Date__00024init__D(environment: UnsafeMutablePointer!, thisClass: jclass, timeIntervalSince1970: jdouble) -> jlong {
- let result$ = UnsafeMutablePointer.allocate(capacity: 1)
- result$.initialize(to: Date.init(timeIntervalSince1970: Double(fromJNI: timeIntervalSince1970, in: environment)))
- let resultBits$ = Int64(Int(bitPattern: result$))
- return resultBits$.getJNILocalRefValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024getTimeIntervalSince1970__J")
-public func Java_org_swift_swiftkit_core_generated_Date__00024getTimeIntervalSince1970__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jdouble {
- assert(selfPointer != 0, "selfPointer memory address was null")
- let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: environment))
- let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$)
- guard let selfPointer$ else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return selfPointer$.pointee.timeIntervalSince1970.getJNILocalRefValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024typeMetadataAddressDowncall__")
-public func Java_org_swift_swiftkit_core_generated_Date__00024typeMetadataAddressDowncall__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
- let metadataPointer = unsafeBitCast(Date.self, to: UnsafeRawPointer.self)
- return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
deleted file mode 100644
index e24e89ffe..000000000
--- a/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
+++ /dev/null
@@ -1,12 +0,0 @@
-// Generated by swift-java
-
-import SwiftJava
-import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
similarity index 63%
rename from SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java
rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
index c6b0f3636..b4f58e69c 100644
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
@@ -1,23 +1,32 @@
-// Generated by jextract-swift
-// Swift module: SwiftJava
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
-package org.swift.swiftkit.core.generated;
+package org.swift.swiftkit.core.foundation;
import org.swift.swiftkit.core.*;
import org.swift.swiftkit.core.util.*;
import org.swift.swiftkit.core.collections.*;
-import java.util.*;
+
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import org.swift.swiftkit.core.annotations.*;
public final class Data implements JNISwiftInstance, DataProtocol {
- static final String LIB_NAME = "SwiftJava";
-
@SuppressWarnings("unused")
private static final boolean INITIALIZED_LIBS = initializeLibs();
static boolean initializeLibs() {
System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
- System.loadLibrary(LIB_NAME);
return true;
}
/**
@@ -29,11 +38,11 @@ static boolean initializeLibs() {
private Data(long selfPointer, SwiftArena swiftArena) {
SwiftObjects.requireNonZero(selfPointer, "selfPointer");
this.selfPointer = selfPointer;
-
+
// Only register once we have fully initialized the object since this will need the object pointer.
swiftArena.register(this);
- } // printConcreteType(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:230
-
+ }
+
/**
* Assume that the passed {@code long} represents a memory address of a {@link Data}.
*
@@ -46,30 +55,30 @@ private Data(long selfPointer, SwiftArena swiftArena) {
public static Data wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
return new Data(selfPointer, swiftArena);
}
-
+
public static Data wrapMemoryAddressUnsafe(long selfPointer) {
return new Data(selfPointer, SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA);
}
/** Pointer to the "self". */
private final long selfPointer;
-
+
/** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */
private final AtomicBoolean $state$destroyed = new AtomicBoolean(false);
-
+
public long $memoryAddress() {
return this.selfPointer;
}
-
+
@Override
public AtomicBoolean $statusDestroyedFlag() {
return $state$destroyed;
}
-
-
-
+
+
+
// ==== --------------------------------------------------
// Data.init
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -78,14 +87,14 @@ public static Data wrapMemoryAddressUnsafe(long selfPointer) {
*/
public static Data init(@Unsigned byte[] bytes, SwiftArena swiftArena) {
return Data.wrapMemoryAddressUnsafe(Data.$init(Objects.requireNonNull(bytes, "bytes must not be null")), swiftArena);
- } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ }
private static native long $init(byte[] bytes);
-
-
-
+
+
+
// ==== --------------------------------------------------
// getter:Data.count
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -94,23 +103,67 @@ public static Data init(@Unsigned byte[] bytes, SwiftArena swiftArena) {
*/
public long getCount() {
return Data.$getCount(this.$memoryAddress());
- } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ }
private static native long $getCount(long selfPointer);
-
+
+ /**
+ * Creates a new Swift @{link Data} instance from a byte array.
+ *
+ * @param bytes The byte array to copy into the Data
+ * @param swiftArena The arena for memory management
+ * @return A new Data instance containing a copy of the bytes
+ */
+ public static Data fromByteArray(byte[] bytes, SwiftArena swiftArena) {
+ Objects.requireNonNull(bytes, "bytes cannot be null");
+ return Data.init(bytes, swiftArena);
+ }
+
+ /**
+ * Copies the contents of this Data to a new byte array.
+ *
+ * This is a relatively efficient implementation, which avoids native array copies,
+ * however it will still perform a copy of the data onto the JVM heap, so use this
+ * only when necessary.
+ *
+ * When utmost performance is necessary, you may want to investigate the FFM mode
+ * of jextract which is able to map memory more efficiently.
+ *
+ * @return A byte array containing a copy of this Data's bytes
+ */
+ public byte[] toByteArray() {
+ return $toByteArray(this.$memoryAddress());
+ }
+ private static native byte[] $toByteArray(long selfPointer);
+
+ /**
+ * Copies the contents of this Data to a new byte array.
+ *
+ * @deprecated Prefer using the `toByteArray` method as it is more performant.
+ * This implementation uses a naive conversion path from native bytes into jbytes
+ * and then copying them onto the jvm heap.
+ *
+ * @return A byte array containing a copy of this Data's bytes
+ */
+ @Deprecated(forRemoval = true)
+ public byte[] toByteArrayIndirectCopy() {
+ return $toByteArrayIndirectCopy(this.$memoryAddress());
+ }
+ private static native byte[] $toByteArrayIndirectCopy(long selfPointer);
+
private static native long $typeMetadataAddressDowncall();
@Override
public long $typeMetadataAddress() {
return Data.$typeMetadataAddressDowncall();
- } // printTypeMetadataAddressFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:776
-
+ }
+
public String toString() {
return SwiftObjects.toString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
public String toDebugString() {
return SwiftObjects.toDebugString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
@Override
public Runnable $createDestroyFunction() {
long self$ = this.$memoryAddress();
@@ -129,5 +182,5 @@ public void run() {
SwiftObjects.destroy(self$, selfType$);
}
};
- } // printDestroyFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:790
-} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:402
+ }
+}
diff --git a/Sources/FakeFoundation/DataProtocol.swift b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
similarity index 76%
rename from Sources/FakeFoundation/DataProtocol.swift
rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
index d5a02d423..f3240bc0d 100644
--- a/Sources/FakeFoundation/DataProtocol.swift
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
@@ -12,10 +12,9 @@
//
//===----------------------------------------------------------------------===//
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
+package org.swift.swiftkit.core.foundation;
-public protocol DataProtocol {}
+import org.swift.swiftkit.core.JNISwiftInstance;
+
+public interface DataProtocol extends JNISwiftInstance {
+}
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
similarity index 62%
rename from SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java
rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
index 1e32774b5..157fe4f81 100644
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
@@ -1,23 +1,31 @@
-// Generated by jextract-swift
-// Swift module: SwiftJava
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
-package org.swift.swiftkit.core.generated;
+package org.swift.swiftkit.core.foundation;
import org.swift.swiftkit.core.*;
import org.swift.swiftkit.core.util.*;
import org.swift.swiftkit.core.collections.*;
-import java.util.*;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import org.swift.swiftkit.core.annotations.*;
public final class Date implements JNISwiftInstance {
- static final String LIB_NAME = "SwiftJava";
-
@SuppressWarnings("unused")
private static final boolean INITIALIZED_LIBS = initializeLibs();
static boolean initializeLibs() {
System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
- System.loadLibrary(LIB_NAME);
return true;
}
/**
@@ -29,11 +37,11 @@ static boolean initializeLibs() {
private Date(long selfPointer, SwiftArena swiftArena) {
SwiftObjects.requireNonZero(selfPointer, "selfPointer");
this.selfPointer = selfPointer;
-
+
// Only register once we have fully initialized the object since this will need the object pointer.
swiftArena.register(this);
- } // printConcreteType(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:230
-
+ }
+
/**
* Assume that the passed {@code long} represents a memory address of a {@link Date}.
*
@@ -46,29 +54,29 @@ private Date(long selfPointer, SwiftArena swiftArena) {
public static Date wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
return new Date(selfPointer, swiftArena);
}
-
+
public static Date wrapMemoryAddressUnsafe(long selfPointer) {
return new Date(selfPointer, SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA);
}
/** Pointer to the "self". */
private final long selfPointer;
-
+
/** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */
private final AtomicBoolean $state$destroyed = new AtomicBoolean(false);
-
+
public long $memoryAddress() {
return this.selfPointer;
}
-
+
@Override
public AtomicBoolean $statusDestroyedFlag() {
return $state$destroyed;
}
-
-
+
+
// ==== --------------------------------------------------
// Date.init
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -77,13 +85,13 @@ public static Date wrapMemoryAddressUnsafe(long selfPointer) {
*/
public static Date init(double timeIntervalSince1970, SwiftArena swiftArena) {
return Date.wrapMemoryAddressUnsafe(Date.$init(timeIntervalSince1970), swiftArena);
- } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ }
private static native long $init(double timeIntervalSince1970);
-
-
+
+
// ==== --------------------------------------------------
// getter:Date.timeIntervalSince1970
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -92,23 +100,66 @@ public static Date init(double timeIntervalSince1970, SwiftArena swiftArena) {
*/
public double getTimeIntervalSince1970() {
return Date.$getTimeIntervalSince1970(this.$memoryAddress());
- } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ }
private static native double $getTimeIntervalSince1970(long selfPointer);
-
+
+ /**
+ * Converts this wrapped date to a Java {@link java.time.Instant}.
+ *
+ * This method constructs the {@code Instant} using the underlying {@code double} value
+ * representing seconds since the Unix Epoch (January 1, 1970).
+ *
+ *
+ * @return A {@code java.time.Instant} derived from the floating-point timestamp.
+ */
+ public java.time.Instant toInstant() {
+ long seconds = (long) this.getTimeIntervalSince1970();
+ long nanos = Math.round((this.getTimeIntervalSince1970() - seconds) * 1_000_000_000);
+ return java.time.Instant.ofEpochSecond(seconds, nanos);
+ }
+
+ /**
+ * Initializes a Swift {@code Foundation.Date} from a Java {@link java.time.Instant}.
+ *
+ * Warning: Precision Loss
+ *
+ * The input precision will be degraded.
+ *
+ *
+ * Java's {@code Instant} stores time with nanosecond precision (9 decimal places).
+ * However, this class stores time as a 64-bit floating-point value.
+ *
+ *
+ * This leaves enough capacity for microsecond precision (approx. 6 decimal places).
+ *
+ *
+ * Consequently, the last ~3 digits of the {@code Instant}'s nanosecond field will be
+ * truncated or subjected to rounding errors during conversion.
+ *
+ *
+ * @param instant The source timestamp to convert.
+ * @return A date derived from the input instant with microsecond precision.
+ */
+ public static Date fromInstant(java.time.Instant instant, SwiftArena swiftArena) {
+ Objects.requireNonNull(instant, "Instant cannot be null");
+ double timeIntervalSince1970 = instant.getEpochSecond() + (instant.getNano() / 1_000_000_000.0);
+ return Date.init(timeIntervalSince1970, swiftArena);
+ }
+
private static native long $typeMetadataAddressDowncall();
@Override
public long $typeMetadataAddress() {
return Date.$typeMetadataAddressDowncall();
- } // printTypeMetadataAddressFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:776
-
+ }
+
public String toString() {
return SwiftObjects.toString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
public String toDebugString() {
return SwiftObjects.toDebugString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
@Override
public Runnable $createDestroyFunction() {
long self$ = this.$memoryAddress();
@@ -127,5 +178,5 @@ public void run() {
SwiftObjects.destroy(self$, selfType$);
}
};
- } // printDestroyFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:790
-} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:402
+ }
+}
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
deleted file mode 100644
index 8e9c0b90f..000000000
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
+++ /dev/null
@@ -1,14 +0,0 @@
-// Generated by jextract-swift
-// Swift module: SwiftJava
-
-package org.swift.swiftkit.core.generated;
-
-import org.swift.swiftkit.core.*;
-import org.swift.swiftkit.core.util.*;
-import org.swift.swiftkit.core.collections.*;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.swift.swiftkit.core.annotations.*;
-
-public interface DataProtocol extends JNISwiftInstance {
-} // printProtocol(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:154
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
deleted file mode 100644
index 0a19e273c..000000000
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Generated by jextract-swift
-// Swift module: SwiftJava
-
-package org.swift.swiftkit.core.generated;
-
-import org.swift.swiftkit.core.*;
-import org.swift.swiftkit.core.util.*;
-import org.swift.swiftkit.core.collections.*;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.swift.swiftkit.core.annotations.*;
-
-public final class SwiftJava {
- static final String LIB_NAME = "SwiftJava";
-
- static {
- System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
- System.loadLibrary(LIB_NAME);
- }
-} // printModuleClass(_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:410
From ce6ec4cde3af1f209ea0c964457384a6558f739a Mon Sep 17 00:00:00 2001
From: Iceman
Date: Mon, 6 Apr 2026 12:56:23 +0900
Subject: [PATCH 03/17] implement without macro for jbytearray returning
functions
---
.../test/java/com/example/swift/DateTest.java | 3 +-
.../java/com/example/swift/OptionalsTest.java | 5 +-
...ift2JavaGenerator+SwiftThunkPrinting.swift | 62 -------------------
.../Foundation/Data+JNI.swift | 55 ++++++++++------
4 files changed, 40 insertions(+), 85 deletions(-)
diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java
index 9b13f37ec..36da11d9d 100644
--- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java
+++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java
@@ -16,6 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
+import org.swift.swiftkit.core.foundation.Date;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
@@ -59,4 +60,4 @@ void date_timeIntervalSince1970() {
assertEquals(1000, date.getTimeIntervalSince1970());
}
}
-}
\ No newline at end of file
+}
diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java
index 771cffc33..941d2a545 100644
--- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java
+++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java
@@ -14,9 +14,10 @@
package com.example.swift;
-import com.example.swift.MySwiftLibrary;
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
+import org.swift.swiftkit.core.foundation.Data;
+import org.swift.swiftkit.core.foundation.Date;
import java.time.Instant;
import java.util.Optional;
@@ -143,4 +144,4 @@ void optionalThrows() {
assertEquals("swiftError", exception.getMessage());
}
}
-}
\ No newline at end of file
+}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
index 544b1b5ac..24c106c01 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
@@ -347,7 +347,6 @@ extension JNISwift2JavaGenerator {
printer.println()
}
- printSpecificTypeThunks(&printer, type)
printTypeMetadataAddressThunk(&printer, type)
printer.println()
}
@@ -856,67 +855,6 @@ extension JNISwift2JavaGenerator {
}
}
- /// Prints thunks for specific known types like Foundation.Date, Foundation.Data
- private func printSpecificTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) {
- guard let knownType = type.swiftNominal.knownTypeKind else { return }
-
- switch knownType {
- case .foundationData, .essentialsData:
- printFoundationDataThunks(&printer, type)
- printer.println()
-
- default:
- break
- }
- }
-
- /// Prints Swift thunks for Foundation.Data helper methods
- private func printFoundationDataThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) {
- let selfPointerParam = JavaParameter(name: "selfPointer", type: .long)
- let parentName = type.qualifiedName
-
- // Rebind the memory instead of converting, and set the memory directly using 'jniSetArrayRegion' from the buffer
- printCDecl(
- &printer,
- javaMethodName: "$toByteArray",
- parentName: type.effectiveJavaName,
- parameters: [
- selfPointerParam
- ],
- resultType: .array(.byte),
- ) { printer in
- let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, swiftParentName: parentName, selfPointerParam)
-
- printer.print(
- """
- return \(selfVar).pointee.withUnsafeBytes { buffer in
- return buffer.getJNIValue(in: environment)
- }
- """
- )
- }
-
- // Legacy API, also to compare with as a baseline, we could remove it
- printCDecl(
- &printer,
- javaMethodName: "$toByteArrayIndirectCopy",
- parentName: type.effectiveJavaName,
- parameters: [
- selfPointerParam
- ],
- resultType: .array(.byte),
- ) { printer in
- let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, swiftParentName: parentName, selfPointerParam)
-
- printer.print(
- """
- // This is a double copy, we need to initialize the array and then copy into a JVM array in getJNIValue
- return [UInt8](\(selfVar).pointee).getJNIValue(in: environment)
- """
- )
- }
- }
-
private func printFunctionOpenerCall(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
guard let translatedDecl = self.translatedDecl(for: decl) else {
fatalError("Cannot print function opener for a function that can't be translated: \(decl)")
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
index aa391639f..8110af8f3 100644
--- a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
@@ -39,29 +39,44 @@ extension Data {
return Int64(selfPointer$.pointee.count)
}
- @JavaMethod("$toByteArray")
- static func _toByteArray(environment: UnsafeMutablePointer!, selfPointer: Int64) -> [UInt8] {
- let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
- guard let selfPointer$ else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return selfPointer$.pointee.withUnsafeBytes { buffer in
- return buffer.getJNIValue(in: environment)
- }
- }
-
- @JavaMethod("$toByteArrayIndirectCopy")
- static func _toByteArrayIndirectCopy(environment: UnsafeMutablePointer!, selfPointer: Int64) -> [UInt8] {
- let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
- guard let selfPointer$ else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return [UInt8](selfPointer$.pointee)
- }
-
@JavaMethod("$typeMetadataAddressDowncall")
static func _typeMetadataAddressDowncall(environment: UnsafeMutablePointer!) -> Int64 {
let metadataPointer = unsafeBitCast(Data.self, to: UnsafeRawPointer.self)
return Int64(Int(bitPattern: metadataPointer))
}
}
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J")
+public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jbyteArray? {
+ guard let env$ = environment else {
+ fatalError("Missing JNIEnv in downcall to \(#function)")
+ }
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: env$))
+ guard let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$) else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return selfPointer$.pointee.withUnsafeBytes { buffer in
+ return buffer.getJNIValue(in: environment)
+ }
+}
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J")
+public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jbyteArray? {
+ guard let env$ = environment else {
+ fatalError("Missing JNIEnv in downcall to \(#function)")
+ }
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: env$))
+ guard let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$) else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ // This is a double copy, we need to initialize the array and then copy into a JVM array in getJNIValue
+ return [UInt8](selfPointer$.pointee).getJNIValue(in: environment)
+}
From cc176f8508465bf559f022b3f1fb1875ce5bd5ab Mon Sep 17 00:00:00 2001
From: Iceman
Date: Mon, 6 Apr 2026 15:41:46 +0900
Subject: [PATCH 04/17] Remove generate script
---
scripts/swiftkit-jni-generate-bindings.sh | 50 -----------------------
1 file changed, 50 deletions(-)
delete mode 100755 scripts/swiftkit-jni-generate-bindings.sh
diff --git a/scripts/swiftkit-jni-generate-bindings.sh b/scripts/swiftkit-jni-generate-bindings.sh
deleted file mode 100755
index a83e97309..000000000
--- a/scripts/swiftkit-jni-generate-bindings.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/bash
-##===----------------------------------------------------------------------===##
-##
-## This source file is part of the Swift.org open source project
-##
-## Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-## Licensed under Apache License v2.0
-##
-## See LICENSE.txt for license information
-## See CONTRIBUTORS.txt for the list of Swift.org project authors
-##
-## SPDX-License-Identifier: Apache-2.0
-##
-##===----------------------------------------------------------------------===##
-
-# Regenerate FFM bindings for types in SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/
-#
-# Run from the swift-java repository root:
-# ./scripts/swiftkit-ffm-generate-bindings.sh
-
-set -euo pipefail
-
-REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
-
-JAVA_OUTPUT="${REPO_ROOT}/SwiftKitCore/src/main/java"
-JAVA_PACKAGE="org.swift.swiftkit.core.generated"
-
-# Declare types to generate: SWIFT_MODULE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
-TYPES=(
- "SwiftJava Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/generated"
-)
-
-for entry in "${TYPES[@]}"; do
- read -r MODULE INPUT_SWIFT OUTPUT_SWIFT <<< "$entry"
-
- echo "==> Generating ${INPUT_SWIFT}..."
-
- xcrun swift run swift-java jextract \
- --mode jni \
- --swift-module "$MODULE" \
- --input-swift "${REPO_ROOT}/${INPUT_SWIFT}" \
- --output-swift "${REPO_ROOT}/${OUTPUT_SWIFT}" \
- --output-java "$JAVA_OUTPUT" \
- --java-package "$JAVA_PACKAGE"
-
- echo " Swift thunks: ${OUTPUT_SWIFT}/"
- echo " Java output: SwiftKitCore/src/main/java/$(echo "$JAVA_PACKAGE" | tr '.' '/')/"
-done
-
-echo "==> Done."
From ae82915f9e1610e366557fceb0efb3eff23cf92e Mon Sep 17 00:00:00 2001
From: Iceman
Date: Tue, 7 Apr 2026 17:38:11 +0900
Subject: [PATCH 05/17] Fix ffm java generated code
---
.../com/example/swift/HelloJava2Swift.java | 3 +-
...FMSwift2JavaGenerator+FoundationData.swift | 166 -------
...t2JavaGenerator+JavaBindingsPrinting.swift | 14 +-
...MSwift2JavaGenerator+JavaTranslation.swift | 48 ++-
.../FFM/FFMSwift2JavaGenerator.swift | 17 -
.../JavaTypes/JavaType+JDK.swift | 8 +
.../swift/swiftkit/ffm/foundation/Data.java | 406 ++++++++++++++++++
.../swiftkit/ffm/foundation/DataProtocol.java | 75 ++++
8 files changed, 543 insertions(+), 194 deletions(-)
delete mode 100644 Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift
create mode 100644 SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java
create mode 100644 SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java
diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java
index 62c29482a..53fca07b6 100644
--- a/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java
+++ b/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java
@@ -22,6 +22,7 @@
import org.swift.swiftkit.core.SwiftLibraries;
import org.swift.swiftkit.ffm.AllocatingSwiftArena;
import org.swift.swiftkit.ffm.SwiftRuntime;
+import org.swift.swiftkit.ffm.foundation.Data;
import java.util.Optional;
import java.util.OptionalLong;
@@ -85,7 +86,7 @@ static void examples() {
var origBytes = arena.allocateFrom("foobar");
var origDat = Data.init(origBytes, origBytes.byteSize(), arena);
CallTraces.trace("origDat.count = " + origDat.getCount());
-
+
var retDat = MySwiftLibrary.globalReceiveReturnData(origDat, arena);
retDat.withUnsafeBytes((retBytes) -> {
var str = retBytes.getString(0);
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift
deleted file mode 100644
index 7dd054f22..000000000
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift
+++ /dev/null
@@ -1,166 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
-
-import CodePrinting
-import SwiftJavaConfigurationShared
-import SwiftJavaJNICore
-import SwiftSyntax
-import SwiftSyntaxBuilder
-
-import struct Foundation.URL
-
-extension FFMSwift2JavaGenerator {
-
- /// Print Java helper methods for Foundation.Data type
- package func printFoundationDataHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- let typeName = decl.swiftNominal.name
- let thunkNameCopyBytes = "swiftjava_\(swiftModuleName)_\(typeName)_copyBytes__"
-
- printer.printSeparator("\(typeName) helper methods")
-
- // This is primarily here for API parity with the JNI version and easier discovery
- printer.print(
- """
- /**
- * Creates a new Swift {@link \(typeName)} instance from a byte array.
- *
- * @param bytes The byte array to copy into the \(typeName)
- * @param arena The arena for memory management
- * @return A new \(typeName) instance containing a copy of the bytes
- */
- public static \(typeName) fromByteArray(byte[] bytes, AllocatingSwiftArena arena) {
- Objects.requireNonNull(bytes, "bytes cannot be null");
- return \(typeName).init(bytes, arena);
- }
- """
- )
-
- // TODO: Implement a fromByteBuffer as well
-
- // Print the descriptor class for copyBytes native call using the shared helper
- let copyBytesCFunc = CFunction(
- resultType: .void,
- name: thunkNameCopyBytes,
- parameters: [
- CParameter(name: "self", type: .qualified(const: true, volatile: false, type: .pointer(.void))),
- CParameter(name: "destination", type: .pointer(.void)),
- CParameter(name: "count", type: .integral(.ptrdiff_t)),
- ],
- isVariadic: false
- )
- printJavaBindingDescriptorClass(&printer, copyBytesCFunc)
-
- printer.print(
- """
- /**
- * Copies the contents of this \(typeName) to a new {@link MemorySegment}.
- *
- * This is the most efficient way to access \(typeName) bytes from Java when you don't
- * need a {@code byte[]}. The returned segment is valid for the lifetime of the arena.
- *
- * Copy count: 1 (Swift Data -> MemorySegment)
- *
- * @param arena The arena to allocate the segment in
- * @return A MemorySegment containing a copy of this \(typeName)'s bytes
- */
- public MemorySegment toMemorySegment(AllocatingSwiftArena arena) {
- $ensureAlive();
- long count = getCount();
- if (count == 0) return MemorySegment.NULL;
- MemorySegment segment = arena.allocate(count);
- \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
- return segment;
- }
- """
- )
-
- printer.print(
- """
- /**
- * Copies the contents of this \(typeName) to a new {@link ByteBuffer}.
- *
- * The returned {@link java.nio.ByteBuffer} is a view over native memory and is valid for the
- * lifetime of the arena. This avoids an additional copy to the Java heap.
- *
- *
Copy count: 1 (Swift Data -> native memory (managed by passed arena), then zero-copy view)
- *
- * @param arena The arena to allocate the underlying memory in
- * @return A ByteBuffer view of the copied bytes
- */
- public java.nio.ByteBuffer toByteBuffer(AllocatingSwiftArena arena) {
- $ensureAlive();
- long count = getCount();
- if (count == 0) return java.nio.ByteBuffer.allocate(0);
- MemorySegment segment = arena.allocate(count);
- \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
- return segment.asByteBuffer();
- }
- """
- )
-
- printer.print(
- """
- /**
- * Copies the contents of this \(typeName) to a new byte array.
- * The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
- *
- *
Copy count: 2 (Swift Data -> MemorySegment -> byte[])
- *
- *
For better performance when you can work with {@link MemorySegment} or
- * {@link java.nio.ByteBuffer}, prefer {@link #toMemorySegment} or {@link #toByteBuffer}.
- *
- * @param arena The arena to use for temporary native memory allocation
- * @return A byte array containing a copy of this \(typeName)'s bytes
- */
- public byte[] toByteArray(AllocatingSwiftArena arena) {
- $ensureAlive();
- long count = getCount();
- if (count == 0) return new byte[0];
- MemorySegment segment = arena.allocate(count);
- \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
- return segment.toArray(ValueLayout.JAVA_BYTE);
- }
- """
- )
-
- printer.print(
- """
- /**
- * Copies the contents of this \(typeName) to a new byte array.
- * The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
- *
- * This is a convenience method that creates a temporary arena for the copy.
- * For repeated calls, prefer {@link #toByteArray(AllocatingSwiftArena)} to reuse an arena.
- *
- *
Copy count: 2 (Swift Data -> MemorySegment -> byte[])
- *
- *
For better performance when you can work with {@link MemorySegment} or
- * {@link java.nio.ByteBuffer}, prefer {@link #toMemorySegment} or {@link #toByteBuffer}.
- *
- * @return A byte array containing a copy of this \(typeName)'s bytes
- */
- public byte[] toByteArray() {
- $ensureAlive();
- long count = getCount();
- if (count == 0) return new byte[0];
- try (var arena = Arena.ofConfined()) {
- MemorySegment segment = arena.allocate(count);
- \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
- return segment.toArray(ValueLayout.JAVA_BYTE);
- }
- }
- """
- )
- }
-}
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
index cb7eac727..48cf4c331 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -456,6 +456,8 @@ extension FFMSwift2JavaGenerator {
let arena =
if let className = type.className,
analysis.importedTypes[className] != nil
+ || type == .swiftkitFFMFoundationData
+ || type == .swiftkitFFMFoundationDataProtocol
{
// Use passed-in 'SwiftArena' for 'SwiftValue'.
"swiftArena"
@@ -619,8 +621,14 @@ extension FFMSwift2JavaGenerator {
func renderMemoryLayoutValue(for javaType: JavaType) -> String {
if let layout = ForeignValueLayout(javaType: javaType) {
return layout.description
- } else if case .class(package: _, name: let customClass, _) = javaType {
- return ForeignValueLayout(customType: customClass).description
+ } else if case .class(let package, name: let customClass, _) = javaType {
+ let type =
+ if let package {
+ "\(package).\(customClass)"
+ } else {
+ customClass
+ }
+ return ForeignValueLayout(customType: type).description
} else {
fatalError("renderMemoryLayoutValue not supported for \(javaType)")
}
@@ -776,7 +784,7 @@ extension FFMSwift2JavaGenerator.JavaConversionStep {
case .wrapMemoryAddressUnsafe(let inner, let javaType):
let inner = inner.render(&printer, placeholder, placeholderForDowncall: placeholderForDowncall)
- return "\(javaType.className!).wrapMemoryAddressUnsafe(\(inner), swiftArena)"
+ return "\(javaType).wrapMemoryAddressUnsafe(\(inner), swiftArena)"
case .construct(let inner, let javaType):
let inner = inner.render(&printer, placeholder, placeholderForDowncall: placeholderForDowncall)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
index c750fdc0a..decc8a547 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
@@ -464,7 +464,15 @@ extension FFMSwift2JavaGenerator {
)
case .foundationData, .essentialsData:
- break
+ return TranslatedParameter(
+ javaParameters: [
+ JavaParameter(
+ name: parameterName,
+ type: .swiftkitFFMFoundationData
+ )
+ ],
+ conversion: .swiftValueSelfSegment(.placeholder)
+ )
case .swiftJavaError:
// SwiftJavaError is a class — treat as arbitrary nominal type below
@@ -635,10 +643,28 @@ extension FFMSwift2JavaGenerator {
case .nominal(let nominal):
if let knownType = nominal.nominalTypeDecl.knownTypeKind {
switch knownType {
- case .foundationData, .foundationDataProtocol:
- break
- case .essentialsData, .essentialsDataProtocol:
- break
+ case .foundationData, .essentialsData:
+ return TranslatedParameter(
+ javaParameters: [
+ JavaParameter(name: parameterName, type: .class(
+ package: nil,
+ name: "Optional",
+ typeParameters: [.swiftkitFFMFoundationData]
+ ))
+ ],
+ conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
+ )
+ case .foundationDataProtocol, .essentialsDataProtocol:
+ return TranslatedParameter(
+ javaParameters: [
+ JavaParameter(name: parameterName, type: .class(
+ package: nil,
+ name: "Optional",
+ typeParameters: [.swiftkitFFMFoundationDataProtocol]
+ ))
+ ],
+ conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
+ )
default:
throw JavaTranslationError.unhandledType(known: .optional(swiftType))
}
@@ -647,7 +673,7 @@ extension FFMSwift2JavaGenerator {
let translatedTy = try self.translate(swiftType: swiftType)
return TranslatedParameter(
javaParameters: [
- JavaParameter(name: parameterName, type: JavaType(className: "Optional<\(translatedTy.description)>"))
+ JavaParameter(name: parameterName, type: .class(package: nil, name: "Optional", typeParameters: [translatedTy]))
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
)
@@ -750,7 +776,15 @@ extension FFMSwift2JavaGenerator {
)
case .foundationData, .essentialsData:
- break // Implemented as wrapper
+ let javaType: JavaType = .swiftkitFFMFoundationData
+ return TranslatedResult(
+ javaResultType: javaType,
+ annotations: resultAnnotations,
+ outParameters: [
+ JavaParameter(name: "", type: javaType)
+ ],
+ conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType)
+ )
case .unsafePointer, .unsafeMutablePointer:
// FIXME: Implement
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
index 6f5f1b8c6..bf4ef1e80 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
@@ -328,9 +328,6 @@ extension FFMSwift2JavaGenerator {
printFunctionDowncallMethods(&printer, funcDecl)
}
- // Special helper methods for known types (e.g. Data)
- printSpecificTypeHelpers(&printer, decl)
-
if let printSpecialPostExtras = self.getSpecialNominalPostMembersPrinting(decl) {
printSpecialPostExtras(&printer)
} else {
@@ -555,20 +552,6 @@ extension FFMSwift2JavaGenerator {
)
}
- /// Print special helper methods for known types like Foundation.Data
- func printSpecificTypeHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- guard let knownType = decl.swiftNominal.knownTypeKind else {
- return
- }
-
- switch knownType {
- case .foundationData, .essentialsData:
- printFoundationDataHelpers(&printer, decl)
- default:
- break
- }
- }
-
/// Print the `fetchDescription` static helper for SwiftJavaError.
/// This calls the `errorDescription()` downcall to get the error message
/// for the super constructor
diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
index 32e01b26f..6790c5af9 100644
--- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
+++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
@@ -70,4 +70,12 @@ extension JavaType {
static var swiftkitCoreFoundationDataProtocol: JavaType {
.class(package: "org.swift.swiftkit.core.foundation", name: "DataProtocol")
}
+
+ static var swiftkitFFMFoundationData: JavaType {
+ .class(package: "org.swift.swiftkit.ffm.foundation", name: "Data")
+ }
+
+ static var swiftkitFFMFoundationDataProtocol: JavaType {
+ .class(package: "org.swift.swiftkit.ffm.foundation", name: "DataProtocol")
+ }
}
diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java
new file mode 100644
index 000000000..ffeaea2eb
--- /dev/null
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java
@@ -0,0 +1,406 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+package org.swift.swiftkit.ffm.foundation;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.ffm.*;
+import org.swift.swiftkit.ffm.generated.*;
+import org.swift.swiftkit.core.annotations.*;
+import java.lang.foreign.*;
+import java.lang.invoke.*;
+import java.util.*;
+
+public final class Data extends FFMSwiftInstance implements SwiftValue {
+ static final String LIB_NAME = "SwiftRuntimeFunctions";
+ static final Arena LIBRARY_ARENA = Arena.ofAuto();
+ @SuppressWarnings("unused")
+ private static final boolean INITIALIZED_LIBS = initializeLibs();
+ static boolean initializeLibs() {
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_CORE);
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_RUNTIME_FUNCTIONS);
+ SwiftLibraries.loadLibraryWithFallbacks(LIB_NAME);
+ return true;
+ }
+
+ public static final SwiftAnyType TYPE_METADATA =
+ new SwiftAnyType(SwiftRuntime.swiftjava.getType("SwiftRuntimeFunctions", "Data"));
+ public SwiftAnyType $swiftType() {
+ return TYPE_METADATA;
+ }
+
+ public static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment());
+ public GroupLayout $layout() {
+ return $LAYOUT;
+ }
+
+ private Data(MemorySegment segment, AllocatingSwiftArena arena) {
+ super(segment, arena);
+ }
+
+ /**
+ * Assume that the passed {@code MemorySegment} represents a memory address of a {@link Data}.
+ *
+ * Warnings:
+ *
+ * - No checks are performed about the compatibility of the pointed at memory and the actual Data types.
+ * - This operation does not copy, or retain, the pointed at pointer, so its lifetime must be ensured manually to be valid when wrapping.
+ *
+ */
+ public static Data wrapMemoryAddressUnsafe(MemorySegment selfPointer, AllocatingSwiftArena arena) {
+ return new Data(selfPointer, arena);
+ }
+
+ // ==== --------------------------------------------------
+ // Data.init
+
+ /**
+ * {@snippet lang=c :
+ * void swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count(const void *bytes, ptrdiff_t count, void *_result)
+ * }
+ */
+ private static class swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count {
+ private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
+ /* bytes: */SwiftValueLayout.SWIFT_POINTER,
+ /* count: */SwiftValueLayout.SWIFT_INT,
+ /* _result: */SwiftValueLayout.SWIFT_POINTER
+ );
+ private static final MemorySegment ADDR =
+ SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count");
+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ public static void call(java.lang.foreign.MemorySegment bytes, long count, java.lang.foreign.MemorySegment _result) {
+ try {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall(bytes, count, _result);
+ }
+ HANDLE.invokeExact(bytes, count, _result);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ }
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public init(bytes: UnsafeRawPointer, count: Int)
+ * }
+ */
+ public static Data init(java.lang.foreign.MemorySegment bytes, long count, AllocatingSwiftArena swiftArena) throws SwiftIntegerOverflowException {
+ MemorySegment result$ = swiftArena.allocate(Data.$LAYOUT);
+ if (SwiftValueLayout.has32bitSwiftInt) {
+ if (count < Integer.MIN_VALUE || count > Integer.MAX_VALUE) {
+ throw new SwiftIntegerOverflowException("Parameter 'count' overflow: " + count);
+ }
+ }
+ swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count.call(bytes, count, result$);
+ return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
+ }
+
+ // ==== --------------------------------------------------
+ // Data.init
+
+ /**
+ * {@snippet lang=c :
+ * void swiftjava_SwiftRuntimeFunctions_Data_init__(const void *bytes_pointer, ptrdiff_t bytes_count, void *_result)
+ * }
+ */
+ private static class swiftjava_SwiftRuntimeFunctions_Data_init__ {
+ private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
+ /* bytes_pointer: */SwiftValueLayout.SWIFT_POINTER,
+ /* bytes_count: */SwiftValueLayout.SWIFT_INT,
+ /* _result: */SwiftValueLayout.SWIFT_POINTER
+ );
+ private static final MemorySegment ADDR =
+ SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_init__");
+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ public static void call(java.lang.foreign.MemorySegment bytes_pointer, long bytes_count, java.lang.foreign.MemorySegment _result) {
+ try {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall(bytes_pointer, bytes_count, _result);
+ }
+ HANDLE.invokeExact(bytes_pointer, bytes_count, _result);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ }
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public init(_ bytes: [UInt8])
+ * }
+ */
+ public static Data init(@Unsigned byte[] bytes, AllocatingSwiftArena swiftArena) {
+ try(var arena$ = Arena.ofConfined()) {
+ MemorySegment result$ = swiftArena.allocate(Data.$LAYOUT);
+ swiftjava_SwiftRuntimeFunctions_Data_init__.call(arena$.allocateFrom(ValueLayout.JAVA_BYTE, bytes), bytes.length, result$);
+ return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
+ }
+ }
+
+ // ==== --------------------------------------------------
+ // getter:Data.count
+
+ /**
+ * {@snippet lang=c :
+ * ptrdiff_t swiftjava_SwiftRuntimeFunctions_Data_count$get(const void *self)
+ * }
+ */
+ private static class swiftjava_SwiftRuntimeFunctions_Data_count$get {
+ private static final FunctionDescriptor DESC = FunctionDescriptor.of(
+ /* -> */SwiftValueLayout.SWIFT_INT,
+ /* self: */SwiftValueLayout.SWIFT_POINTER
+ );
+ private static final MemorySegment ADDR =
+ SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_count$get");
+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ public static long call(java.lang.foreign.MemorySegment self) {
+ try {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall(self);
+ }
+ return (long) HANDLE.invokeExact(self);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ }
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public var count: Int
+ * }
+ */
+ public long getCount() throws SwiftIntegerOverflowException {
+ $ensureAlive();
+ long result$checked = swiftjava_SwiftRuntimeFunctions_Data_count$get.call(this.$memorySegment());
+ if (SwiftValueLayout.has32bitSwiftInt) {
+ if (result$checked < Integer.MIN_VALUE || result$checked > Integer.MAX_VALUE) {
+ throw new SwiftIntegerOverflowException("Return value overflow: " + result$checked);
+ }
+ }
+ return result$checked;
+ }
+
+ // ==== --------------------------------------------------
+ // Data.withUnsafeBytes
+
+ /**
+ * {@snippet lang=c :
+ * void swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__(void (*body)(const void *, ptrdiff_t), const void *self)
+ * }
+ */
+ private static class swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__ {
+ private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
+ /* body: */SwiftValueLayout.SWIFT_POINTER,
+ /* self: */SwiftValueLayout.SWIFT_POINTER
+ );
+ private static final MemorySegment ADDR =
+ SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__");
+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ public static void call(java.lang.foreign.MemorySegment body, java.lang.foreign.MemorySegment self) {
+ try {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall(body, self);
+ }
+ HANDLE.invokeExact(body, self);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ /**
+ * {snippet lang=c :
+ * void (*)(const void *, ptrdiff_t)
+ * }
+ */
+ private static class $body {
+ @FunctionalInterface
+ public interface Function {
+ void apply(java.lang.foreign.MemorySegment _0, long _1);
+ }
+ private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
+ /* _0: */SwiftValueLayout.SWIFT_POINTER,
+ /* _1: */SwiftValueLayout.SWIFT_INT
+ );
+ private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC);
+ private static MemorySegment toUpcallStub(Function fi, Arena arena) {
+ return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena);
+ }
+ }
+ }
+ public static class withUnsafeBytes {
+ @FunctionalInterface
+ public interface body {
+ void apply(java.lang.foreign.MemorySegment _0);
+ }
+ private static MemorySegment $toUpcallStub(body fi, Arena arena) {
+ return swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__.$body.toUpcallStub((_0_pointer, _0_count) -> {
+ fi.apply(_0_pointer.reinterpret(_0_count));
+ }, arena);
+ }
+ }
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
+ * }
+ */
+ public void withUnsafeBytes(withUnsafeBytes.body body) {
+ $ensureAlive();
+ try(var arena$ = Arena.ofConfined()) {
+ swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__.call(withUnsafeBytes.$toUpcallStub(body, arena$), this.$memorySegment());
+ }
+ }
+
+ // ==== --------------------------------------------------
+ // Data helper methods
+
+ /**
+ * Creates a new Swift {@link Data} instance from a byte array.
+ *
+ * @param bytes The byte array to copy into the Data
+ * @param arena The arena for memory management
+ * @return A new Data instance containing a copy of the bytes
+ */
+ public static Data fromByteArray(byte[] bytes, AllocatingSwiftArena arena) {
+ Objects.requireNonNull(bytes, "bytes cannot be null");
+ return Data.init(bytes, arena);
+ }
+
+ /**
+ * {@snippet lang=c :
+ * void swiftjava_SwiftRuntimeFunctions_Data_copyBytes__(void *const self, void *destination, ptrdiff_t count)
+ * }
+ */
+ private static class swiftjava_SwiftRuntimeFunctions_Data_copyBytes__ {
+ private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
+ /* self: */SwiftValueLayout.SWIFT_POINTER,
+ /* destination: */SwiftValueLayout.SWIFT_POINTER,
+ /* count: */SwiftValueLayout.SWIFT_INT
+ );
+ private static final MemorySegment ADDR =
+ SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_copyBytes__");
+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ public static void call(java.lang.foreign.MemorySegment self, java.lang.foreign.MemorySegment destination, long count) {
+ try {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall(self, destination, count);
+ }
+ HANDLE.invokeExact(self, destination, count);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ }
+
+ /**
+ * Copies the contents of this Data to a new {@link MemorySegment}.
+ *
+ * This is the most efficient way to access Data bytes from Java when you don't
+ * need a {@code byte[]}. The returned segment is valid for the lifetime of the arena.
+ *
+ * Copy count: 1 (Swift Data -> MemorySegment)
+ *
+ * @param arena The arena to allocate the segment in
+ * @return A MemorySegment containing a copy of this Data's bytes
+ */
+ public MemorySegment toMemorySegment(AllocatingSwiftArena arena) {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return MemorySegment.NULL;
+ MemorySegment segment = arena.allocate(count);
+ swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
+ return segment;
+ }
+
+ /**
+ * Copies the contents of this Data to a new {@link java.nio.ByteBuffer}.
+ *
+ * The returned {@link java.nio.ByteBuffer} is a view over native memory and is valid for the
+ * lifetime of the arena. This avoids an additional copy to the Java heap.
+ *
+ *
Copy count: 1 (Swift Data -> native memory (managed by passed arena), then zero-copy view)
+ *
+ * @param arena The arena to allocate the underlying memory in
+ * @return A ByteBuffer view of the copied bytes
+ */
+ public java.nio.ByteBuffer toByteBuffer(AllocatingSwiftArena arena) {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return java.nio.ByteBuffer.allocate(0);
+ MemorySegment segment = arena.allocate(count);
+ swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
+ return segment.asByteBuffer();
+ }
+
+ /**
+ * Copies the contents of this Data to a new byte array.
+ * The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
+ *
+ *
Copy count: 2 (Swift Data -> MemorySegment -> byte[])
+ *
+ *
For better performance when you can work with {@link MemorySegment} or
+ * {@link java.nio.ByteBuffer}, prefer {@link #toMemorySegment} or {@link #toByteBuffer}.
+ *
+ * @param arena The arena to use for temporary native memory allocation
+ * @return A byte array containing a copy of this Data's bytes
+ */
+ public byte[] toByteArray(AllocatingSwiftArena arena) {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return new byte[0];
+ MemorySegment segment = arena.allocate(count);
+ swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
+ return segment.toArray(ValueLayout.JAVA_BYTE);
+ }
+
+ /**
+ * Copies the contents of this Data to a new byte array.
+ * The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
+ *
+ * This is a convenience method that creates a temporary arena for the copy.
+ * For repeated calls, prefer {@link #toByteArray(AllocatingSwiftArena)} to reuse an arena.
+ *
+ *
Copy count: 2 (Swift Data -> MemorySegment -> byte[])
+ *
+ *
For better performance when you can work with {@link MemorySegment} or
+ * {@link java.nio.ByteBuffer}, prefer {@link #toMemorySegment} or {@link #toByteBuffer}.
+ *
+ * @return A byte array containing a copy of this Data's bytes
+ */
+ public byte[] toByteArray() {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return new byte[0];
+ try (var arena = Arena.ofConfined()) {
+ MemorySegment segment = arena.allocate(count);
+ swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
+ return segment.toArray(ValueLayout.JAVA_BYTE);
+ }
+ }
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()
+ + "("
+ + SwiftRuntime.nameOfSwiftType($swiftType().$memorySegment(), true)
+ + ")@"
+ + $memorySegment();
+ }
+}
diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java
new file mode 100644
index 000000000..2881ac85e
--- /dev/null
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+package org.swift.swiftkit.ffm.foundation;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.ffm.*;
+import org.swift.swiftkit.ffm.generated.*;
+import org.swift.swiftkit.core.annotations.*;
+import java.lang.foreign.*;
+import java.lang.invoke.*;
+import java.util.*;
+
+public final class DataProtocol extends FFMSwiftInstance implements SwiftValue {
+ static final String LIB_NAME = "SwiftRuntimeFunctions";
+ static final Arena LIBRARY_ARENA = Arena.ofAuto();
+ @SuppressWarnings("unused")
+ private static final boolean INITIALIZED_LIBS = initializeLibs();
+ static boolean initializeLibs() {
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_CORE);
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_RUNTIME_FUNCTIONS);
+ SwiftLibraries.loadLibraryWithFallbacks(LIB_NAME);
+ return true;
+ }
+
+ public static final SwiftAnyType TYPE_METADATA =
+ new SwiftAnyType(SwiftRuntime.swiftjava.getType("SwiftRuntimeFunctions", "DataProtocol"));
+ public SwiftAnyType $swiftType() {
+ return TYPE_METADATA;
+ }
+
+ public static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment());
+ public GroupLayout $layout() {
+ return $LAYOUT;
+ }
+
+ private DataProtocol(MemorySegment segment, AllocatingSwiftArena arena) {
+ super(segment, arena);
+ }
+
+ /**
+ * Assume that the passed {@code MemorySegment} represents a memory address of a {@link DataProtocol}.
+ *
+ * Warnings:
+ *
+ * - No checks are performed about the compatibility of the pointed at memory and the actual DataProtocol types.
+ * - This operation does not copy, or retain, the pointed at pointer, so its lifetime must be ensured manually to be valid when wrapping.
+ *
+ */
+ public static DataProtocol wrapMemoryAddressUnsafe(MemorySegment selfPointer, AllocatingSwiftArena arena) {
+ return new DataProtocol(selfPointer, arena);
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()
+ + "("
+ + SwiftRuntime.nameOfSwiftType($swiftType().$memorySegment(), true)
+ + ")@"
+ + $memorySegment();
+ }
+}
From c42156ff4b4b530532f12c4cc5cc5fc66ae10cd5 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Tue, 7 Apr 2026 17:52:44 +0900
Subject: [PATCH 06/17] native implementation and fix test import
---
.../swift/swiftkit/ffm/FFMDataBenchmark.java | 3 +-
.../com/example/swift/DataImportTest.java | 3 +-
.../com/example/swift/OptionalImportTest.java | 1 +
.../foundation/Data+FFM.swift | 70 +++++++++++++++++++
4 files changed, 74 insertions(+), 3 deletions(-)
create mode 100644 Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java b/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
index 39a64c7a9..2ce5950f2 100644
--- a/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
+++ b/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
@@ -14,7 +14,6 @@
package org.swift.swiftkit.ffm;
-import com.example.swift.Data;
import com.example.swift.MySwiftLibrary;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
@@ -79,7 +78,7 @@ public ByteBuffer ffm_data_withUnsafeBytes_asByteBuffer() {
});
return buf.value;
}
-
+
@Benchmark
public byte[] ffm_data_withUnsafeBytes_toArray() {
Holder buf = new Holder<>();
diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java
index 82fb09464..69ed9db31 100644
--- a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java
+++ b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java
@@ -16,6 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.ffm.AllocatingSwiftArena;
+import org.swift.swiftkit.ffm.foundation.Data;
import java.lang.foreign.ValueLayout;
@@ -134,7 +135,7 @@ void test_Data_toByteBuffer_emptyData() {
byte[] original = new byte[0];
var data = Data.fromByteArray(original, arena);
var buffer = data.toByteBuffer(arena);
-
+
assertEquals(0, buffer.capacity());
}
}
diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/OptionalImportTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/OptionalImportTest.java
index 57e8dba61..306ce688c 100644
--- a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/OptionalImportTest.java
+++ b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/OptionalImportTest.java
@@ -16,6 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.ffm.AllocatingSwiftArena;
+import org.swift.swiftkit.ffm.foundation.Data;
import java.util.Optional;
import java.util.OptionalLong;
diff --git a/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift b/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
new file mode 100644
index 000000000..157abe53e
--- /dev/null
+++ b/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+
+// ==== --------------------------------------------------
+// Thunks for Data
+
+@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_Data")
+public func swiftjava_getType_SwiftRuntimeFunctions_Data() -> UnsafeMutableRawPointer /* Any.Type */ {
+ return unsafeBitCast(Data.self, to: UnsafeMutableRawPointer.self)
+}
+
+@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count")
+public func swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count(_ bytes: UnsafeRawPointer, _ count: Int, _ _result: UnsafeMutableRawPointer) {
+ _result.assumingMemoryBound(to: Data.self).initialize(to: Data(bytes: bytes, count: count))
+}
+
+@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_init__")
+public func swiftjava_SwiftRuntimeFunctions_Data_init__(_ bytes_pointer: UnsafeRawPointer, _ bytes_count: Int, _ _result: UnsafeMutableRawPointer) {
+ _result.assumingMemoryBound(to: Data.self).initialize(to: Data([UInt8](UnsafeRawBufferPointer(start: bytes_pointer, count: bytes_count))))
+}
+
+@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_count$get")
+public func swiftjava_SwiftRuntimeFunctions_Data_count$get(_ self: UnsafeRawPointer) -> Int {
+ return self.assumingMemoryBound(to: Data.self).pointee.count
+}
+
+@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__")
+public func swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__(_ body: @convention(c) (UnsafeRawPointer?, Int) -> Void, _ self: UnsafeRawPointer) {
+ self.assumingMemoryBound(to: Data.self).pointee.withUnsafeBytes({ (_0) in
+ return body(_0.baseAddress, _0.count)
+ })
+}
+
+@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_copyBytes__")
+public func swiftjava_SwiftRuntimeFunctions_Data_copyBytes__(
+ selfPointer: UnsafeRawPointer,
+ destinationPointer: UnsafeMutableRawPointer,
+ count: Int
+) {
+ let data = selfPointer.assumingMemoryBound(to: Data.self).pointee
+ data.withUnsafeBytes { buffer in
+ destinationPointer.copyMemory(from: buffer.baseAddress!, byteCount: count)
+ }
+}
+
+// ==== --------------------------------------------------
+// Thunks for DataProtocol
+
+@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_DataProtocol")
+public func swiftjava_getType_SwiftRuntimeFunctions_DataProtocol() -> UnsafeMutableRawPointer /* Any.Type */ {
+ return unsafeBitCast((any DataProtocol).self, to: UnsafeMutableRawPointer.self)
+}
From afae76e66ce8a779bc5955f68155252278bb313a Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 10:22:08 +0900
Subject: [PATCH 07/17] Fix test cases
---
.../JExtractSwiftTests/DataImportTests.swift | 253 +-----------------
Tests/JExtractSwiftTests/DateTests.swift | 149 +++--------
.../JNI/JNIDictionaryTest.swift | 16 +-
Tests/JExtractSwiftTests/JNI/JNISetTest.swift | 12 +-
.../OptionalImportTests.swift | 2 +-
.../SwiftSymbolTableTests.swift | 8 +-
6 files changed, 58 insertions(+), 382 deletions(-)
diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift
index e67a3db87..c2ce81ca5 100644
--- a/Tests/JExtractSwiftTests/DataImportTests.swift
+++ b/Tests/JExtractSwiftTests/DataImportTests.swift
@@ -95,36 +95,6 @@ final class DataImportTests {
_result.assumingMemoryBound(to: Data.self).initialize(to: returnData())
}
""",
-
- """
- @_cdecl("swiftjava_getType_SwiftModule_Data")
- public func swiftjava_getType_SwiftModule_Data() -> UnsafeMutableRawPointer /* Any.Type */ {
- return unsafeBitCast(Data.self, to: UnsafeMutableRawPointer.self)
- }
- """,
-
- """
- @_cdecl("swiftjava_SwiftModule_Data_init_bytes_count")
- public func swiftjava_SwiftModule_Data_init_bytes_count(_ bytes: UnsafeRawPointer, _ count: Int, _ _result: UnsafeMutableRawPointer) {
- _result.assumingMemoryBound(to: Data.self).initialize(to: Data(bytes: bytes, count: count))
- }
- """,
-
- """
- @_cdecl("swiftjava_SwiftModule_Data_count$get")
- public func swiftjava_SwiftModule_Data_count$get(_ self: UnsafeRawPointer) -> Int {
- return self.assumingMemoryBound(to: Data.self).pointee.count
- }
- """,
-
- """
- @_cdecl("swiftjava_SwiftModule_Data_withUnsafeBytes__")
- public func swiftjava_SwiftModule_Data_withUnsafeBytes__(_ body: @convention(c) (UnsafeRawPointer?, Int) -> Void, _ self: UnsafeRawPointer) {
- self.assumingMemoryBound(to: Data.self).pointee.withUnsafeBytes({ (_0) in
- return body(_0.baseAddress, _0.count)
- })
- }
- """,
]
)
}
@@ -174,7 +144,7 @@ final class DataImportTests {
* public func receiveData(dat: Data)
* }
*/
- public static void receiveData(Data dat) {
+ public static void receiveData(org.swift.swiftkit.ffm.foundation.Data dat) {
swiftjava_SwiftModule_receiveData_dat.call(dat.$memorySegment());
}
""",
@@ -212,178 +182,10 @@ final class DataImportTests {
* public func returnData() -> Data
* }
*/
- public static Data returnData(AllocatingSwiftArena swiftArena) {
- MemorySegment result$ = swiftArena.allocate(Data.$LAYOUT);
+ public static org.swift.swiftkit.ffm.foundation.Data returnData(AllocatingSwiftArena swiftArena) {
+ MemorySegment result$ = swiftArena.allocate(org.swift.swiftkit.ffm.foundation.Data.$LAYOUT);
swiftjava_SwiftModule_returnData.call(result$);
- return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
- }
- """,
-
- """
- /**
- * {@snippet lang=c :
- * void swiftjava_SwiftModule_Data_init_bytes_count(const void *bytes, ptrdiff_t count, void *_result)
- * }
- */
- private static class swiftjava_SwiftModule_Data_init_bytes_count {
- private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
- /* bytes: */SwiftValueLayout.SWIFT_POINTER,
- /* count: */SwiftValueLayout.SWIFT_INT,
- /* _result: */SwiftValueLayout.SWIFT_POINTER
- );
- private static final MemorySegment ADDR =
- SwiftModule.findOrThrow("swiftjava_SwiftModule_Data_init_bytes_count");
- private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
- public static void call(java.lang.foreign.MemorySegment bytes, long count, java.lang.foreign.MemorySegment _result) {
- try {
- if (CallTraces.TRACE_DOWNCALLS) {
- CallTraces.traceDowncall(bytes, count, _result);
- }
- HANDLE.invokeExact(bytes, count, _result);
- } catch (Throwable ex$) {
- throw new AssertionError("should not reach here", ex$);
- }
- }
- }
- """,
-
- """
- /**
- * Downcall to Swift:
- * {@snippet lang=swift :
- * public init(bytes: UnsafeRawPointer, count: Int)
- * }
- */
- public static Data init(java.lang.foreign.MemorySegment bytes, long count, AllocatingSwiftArena swiftArena) throws SwiftIntegerOverflowException {
- MemorySegment result$ = swiftArena.allocate(Data.$LAYOUT);
- if (SwiftValueLayout.has32bitSwiftInt) {
- if (count < Integer.MIN_VALUE || count > Integer.MAX_VALUE) {
- throw new SwiftIntegerOverflowException("Parameter 'count' overflow: " + count);
- }
- }
- swiftjava_SwiftModule_Data_init_bytes_count.call(bytes, count, result$);
- return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
- }
- """,
-
- """
- /**
- * {@snippet lang=c :
- * ptrdiff_t swiftjava_SwiftModule_Data_count$get(const void *self)
- * }
- */
- private static class swiftjava_SwiftModule_Data_count$get {
- private static final FunctionDescriptor DESC = FunctionDescriptor.of(
- /* -> */SwiftValueLayout.SWIFT_INT,
- /* self: */SwiftValueLayout.SWIFT_POINTER
- );
- private static final MemorySegment ADDR =
- SwiftModule.findOrThrow("swiftjava_SwiftModule_Data_count$get");
- private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
- public static long call(java.lang.foreign.MemorySegment self) {
- try {
- if (CallTraces.TRACE_DOWNCALLS) {
- CallTraces.traceDowncall(self);
- }
- return (long) HANDLE.invokeExact(self);
- } catch (Throwable ex$) {
- throw new AssertionError("should not reach here", ex$);
- }
- }
- }
- """,
-
- """
- /**
- * Downcall to Swift:
- * {@snippet lang=swift :
- * public var count: Int
- * }
- */
- public long getCount() throws SwiftIntegerOverflowException {
- $ensureAlive();
- long result$checked = swiftjava_SwiftModule_Data_count$get.call(this.$memorySegment());
- if (SwiftValueLayout.has32bitSwiftInt) {
- if (result$checked < Integer.MIN_VALUE || result$checked > Integer.MAX_VALUE) {
- throw new SwiftIntegerOverflowException("Return value overflow: " + result$checked);
- }
- }
- return result$checked;
- }
- """,
-
- """
- /**
- * {@snippet lang=c :
- * void swiftjava_SwiftModule_Data_withUnsafeBytes__(void (*body)(const void *, ptrdiff_t), const void *self)
- * }
- */
- private static class swiftjava_SwiftModule_Data_withUnsafeBytes__ {
- private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
- /* body: */SwiftValueLayout.SWIFT_POINTER,
- /* self: */SwiftValueLayout.SWIFT_POINTER
- );
- private static final MemorySegment ADDR =
- SwiftModule.findOrThrow("swiftjava_SwiftModule_Data_withUnsafeBytes__");
- private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
- public static void call(java.lang.foreign.MemorySegment body, java.lang.foreign.MemorySegment self) {
- try {
- if (CallTraces.TRACE_DOWNCALLS) {
- CallTraces.traceDowncall(body, self);
- }
- HANDLE.invokeExact(body, self);
- } catch (Throwable ex$) {
- throw new AssertionError("should not reach here", ex$);
- }
- }
- /**
- * {snippet lang=c :
- * void (*)(const void *, ptrdiff_t)
- * }
- */
- private static class $body {
- @FunctionalInterface
- public interface Function {
- void apply(java.lang.foreign.MemorySegment _0, long _1);
- }
- private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
- /* _0: */SwiftValueLayout.SWIFT_POINTER,
- /* _1: */SwiftValueLayout.SWIFT_INT
- );
- private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC);
- private static MemorySegment toUpcallStub(Function fi, Arena arena) {
- return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena);
- }
- }
- }
- """,
-
- """
- public static class withUnsafeBytes {
- @FunctionalInterface
- public interface body {
- void apply(java.lang.foreign.MemorySegment _0);
- }
- private static MemorySegment $toUpcallStub(body fi, Arena arena) {
- return swiftjava_SwiftModule_Data_withUnsafeBytes__.$body.toUpcallStub((_0_pointer, _0_count) -> {
- fi.apply(_0_pointer.reinterpret(_0_count));
- }, arena);
- }
- }
- """,
-
- """
- /**
- * Downcall to Swift:
- * {@snippet lang=swift :
- * public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
- * }
- */
- public void withUnsafeBytes(withUnsafeBytes.body body) {
- $ensureAlive();
- try(var arena$ = Arena.ofConfined()) {
- swiftjava_SwiftModule_Data_withUnsafeBytes__.call(withUnsafeBytes.$toUpcallStub(body, arena$), this.$memorySegment());
- }
+ return org.swift.swiftkit.ffm.foundation.Data.wrapMemoryAddressUnsafe(result$, swiftArena);
}
""",
]
@@ -413,11 +215,6 @@ final class DataImportTests {
receiveDataProtocol(dat: dat.assumingMemoryBound(to: Data.self).pointee, dat2: dat2?.assumingMemoryBound(to: Data.self).pointee)
}
""",
-
- // Just to make sure 'Data' is imported.
- """
- @_cdecl("swiftjava_getType_SwiftModule_Data")
- """,
]
)
}
@@ -470,15 +267,10 @@ final class DataImportTests {
* public func receiveDataProtocol(dat: some DataProtocol, dat2: T?)
* }
*/
- public static void receiveDataProtocol(Data dat, Optional dat2) {
+ public static void receiveDataProtocol(org.swift.swiftkit.ffm.foundation.Data dat, Optional dat2) {
swiftjava_SwiftModule_receiveDataProtocol_dat_dat2.call(dat.$memorySegment(), SwiftRuntime.toOptionalSegmentInstance(dat2));
}
""",
-
- // Just to make sure 'Data' is imported.
- """
- public final class Data extends FFMSwiftInstance implements SwiftValue {
- """,
]
)
}
@@ -499,7 +291,7 @@ final class DataImportTests {
detectChunkByInitialLines: 1,
expectedChunks: [
"""
- public static void acceptData(Data data) {
+ public static void acceptData(org.swift.swiftkit.core.foundation.Data data) {
SwiftModule.$acceptData(data.$memoryAddress());
}
"""
@@ -533,7 +325,7 @@ final class DataImportTests {
.java,
expectedChunks: [
"""
- public static Data returnData(SwiftArena swiftArena) {
+ public static org.swift.swiftkit.core.foundation.Data returnData(SwiftArena swiftArena) {
"""
]
)
@@ -551,33 +343,6 @@ final class DataImportTests {
)
}
- @Test("Import Data: JNI Data class")
- func data_jni_class() throws {
- let text = """
- import Foundation
- public func f() -> Data
- """
-
- try assertOutput(
- input: text,
- .jni,
- .java,
- detectChunkByInitialLines: 1,
- expectedChunks: [
- "public final class Data implements JNISwiftInstance, DataProtocol {",
- "public long getCount() {",
-
- "public static Data fromByteArray(byte[] bytes, SwiftArena swiftArena) {",
-
- "public byte[] toByteArray() {",
- "private static native byte[] $toByteArray(long selfPointer);",
-
- "public byte[] toByteArrayIndirectCopy() {",
- "private static native byte[] $toByteArrayIndirectCopy(long selfPointer);",
- ]
- )
- }
-
// ==== -----------------------------------------------------------------------
// MARK: JNI DataProtocol generic parameter
@@ -599,7 +364,7 @@ final class DataImportTests {
detectChunkByInitialLines: 2,
expectedChunks: [
"""
- public static MyResult processData(D data, SwiftArena swiftArena) {
+ public static MyResult processData(D data, SwiftArena swiftArena) {
"""
]
)
@@ -620,7 +385,7 @@ final class DataImportTests {
detectChunkByInitialLines: 2,
expectedChunks: [
"""
- public static boolean verify(D1 first, D2 second) {
+ public static boolean verify(D1 first, D2 second) {
"""
]
)
diff --git a/Tests/JExtractSwiftTests/DateTests.swift b/Tests/JExtractSwiftTests/DateTests.swift
index bf5e9ef8e..13a1e59f1 100644
--- a/Tests/JExtractSwiftTests/DateTests.swift
+++ b/Tests/JExtractSwiftTests/DateTests.swift
@@ -17,34 +17,8 @@ import SwiftJavaConfigurationShared
import Testing
struct DateTests {
- @Test(
- "Import: accept Date",
- arguments: [
- (
- JExtractGenerationMode.jni,
- /* expected Java chunks */
- [
- """
- public static void acceptDate(Date date) {
- SwiftModule.$acceptDate(date.$memoryAddress());
- }
- """
- ],
- /* expected Swift chunks */
- [
- """
- @_cdecl("Java_com_example_swift_SwiftModule__00024acceptDate__J")
- public func Java_com_example_swift_SwiftModule__00024acceptDate__J(environment: UnsafeMutablePointer!, thisClass: jclass, date: jlong) {
- """
- ],
- )
- ]
- )
- func func_accept_date(
- mode: JExtractGenerationMode,
- expectedJavaChunks: [String],
- expectedSwiftChunks: [String]
- ) throws {
+ @Test("Import: accept Date")
+ func func_accept_date() throws {
let text =
"""
import Foundation
@@ -54,47 +28,34 @@ struct DateTests {
try assertOutput(
input: text,
- mode,
+ .jni,
.java,
detectChunkByInitialLines: 1,
- expectedChunks: expectedJavaChunks
+ expectedChunks: [
+ """
+ public static void acceptDate(org.swift.swiftkit.core.foundation.Date date) {
+ SwiftModule.$acceptDate(date.$memoryAddress());
+ }
+ """
+ ]
)
try assertOutput(
input: text,
- mode,
+ .jni,
.swift,
detectChunkByInitialLines: 1,
- expectedChunks: expectedSwiftChunks
+ expectedChunks: [
+ """
+ @_cdecl("Java_com_example_swift_SwiftModule__00024acceptDate__J")
+ public func Java_com_example_swift_SwiftModule__00024acceptDate__J(environment: UnsafeMutablePointer!, thisClass: jclass, date: jlong) {
+ """
+ ]
)
}
- @Test(
- "Import: return Date",
- arguments: [
- (
- JExtractGenerationMode.jni,
- /* expected Java chunks */
- [
- """
- public static Date returnDate(SwiftArena swiftArena) {
- """
- ],
- /* expected Swift chunks */
- [
- """
- @_cdecl("Java_com_example_swift_SwiftModule__00024returnDate__")
- public func Java_com_example_swift_SwiftModule__00024returnDate__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
- """
- ]
- )
- ]
- )
- func func_return_Date(
- mode: JExtractGenerationMode,
- expectedJavaChunks: [String],
- expectedSwiftChunks: [String]
- ) throws {
+ @Test("Import: return Date")
+ func func_return_Date() throws {
let text =
"""
import Foundation
@@ -103,75 +64,25 @@ struct DateTests {
try assertOutput(
input: text,
- mode,
+ .jni,
.java,
- expectedChunks: expectedJavaChunks
- )
-
- try assertOutput(
- input: text,
- mode,
- .swift,
- expectedChunks: expectedSwiftChunks
- )
- }
-
- @Test(
- "Import: Date type",
- arguments: [
- (
- JExtractGenerationMode.jni,
- /* expected Java chunks */
- [
+ expectedChunks: [
"""
- public final class Date implements JNISwiftInstance {
- """,
+ public static org.swift.swiftkit.core.foundation.Date returnDate(SwiftArena swiftArena) {
"""
- public static Date init(double timeIntervalSince1970, SwiftArena swiftArena) {
- """,
- """
- public double getTimeIntervalSince1970() {
- """,
- """
- public static Date fromInstant(java.time.Instant instant, SwiftArena swiftArena) {
- """,
- """
- public java.time.Instant toInstant() {
- """,
- ],
- /* expected Swift chunks */
- [
- """
- @_cdecl("Java_com_example_swift_Date__00024init__D")
- public func Java_com_example_swift_Date__00024init__D(environment: UnsafeMutablePointer!, thisClass: jclass, timeIntervalSince1970: jdouble) -> jlong {
- """,
- """
- @_cdecl("Java_com_example_swift_Date__00024getTimeIntervalSince1970__J")
- public func Java_com_example_swift_Date__00024getTimeIntervalSince1970__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jdouble {
- """,
- ]
- )
- ]
- )
- func date_class(mode: JExtractGenerationMode, expectedJavaChunks: [String], expectedSwiftChunks: [String]) throws {
- let text =
- """
- import Foundation
- public func f() -> Date
- """
-
- try assertOutput(
- input: text,
- mode,
- .java,
- expectedChunks: expectedJavaChunks
+ ],
)
try assertOutput(
input: text,
- mode,
+ .jni,
.swift,
- expectedChunks: expectedSwiftChunks
+ expectedChunks: [
+ """
+ @_cdecl("Java_com_example_swift_SwiftModule__00024returnDate__")
+ public func Java_com_example_swift_SwiftModule__00024returnDate__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
+ """
+ ]
)
}
}
diff --git a/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift b/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift
index 0690ee01d..ebb8ed163 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift
@@ -28,7 +28,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
""",
"""
@@ -104,7 +104,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(org.swift.swiftkit.core.collections.SwiftDictionaryMap dict, SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena);
}
""",
"""
@@ -142,7 +142,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(org.swift.swiftkit.core.collections.SwiftDictionaryMap dict, SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena);
}
""",
"""
@@ -183,7 +183,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -200,7 +200,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -217,7 +217,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -234,7 +234,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -295,7 +295,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(org.swift.swiftkit.core.collections.SwiftDictionaryMap dict, java.lang.String key, long value, SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress(), key, value), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress(), key, value), swiftArena);
}
""",
"""
diff --git a/Tests/JExtractSwiftTests/JNI/JNISetTest.swift b/Tests/JExtractSwiftTests/JNI/JNISetTest.swift
index e654344d2..8adec8d58 100644
--- a/Tests/JExtractSwiftTests/JNI/JNISetTest.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNISetTest.swift
@@ -28,7 +28,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
""",
"""
@@ -104,7 +104,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(org.swift.swiftkit.core.collections.SwiftSet set, SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress()), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress()), swiftArena);
}
""",
"""
@@ -145,7 +145,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -162,7 +162,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -179,7 +179,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -240,7 +240,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(org.swift.swiftkit.core.collections.SwiftSet set, java.lang.String element, SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress(), element), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress(), element), swiftArena);
}
""",
"""
diff --git a/Tests/JExtractSwiftTests/OptionalImportTests.swift b/Tests/JExtractSwiftTests/OptionalImportTests.swift
index fc169fe53..ea20272e3 100644
--- a/Tests/JExtractSwiftTests/OptionalImportTests.swift
+++ b/Tests/JExtractSwiftTests/OptionalImportTests.swift
@@ -146,7 +146,7 @@ final class OptionalImportTests {
* public func receiveOptionalDataProto(_ arg: (some DataProtocol)?)
* }
*/
- public static void receiveOptionalDataProto(Optional arg) {
+ public static void receiveOptionalDataProto(Optional arg) {
swiftjava_SwiftModule_receiveOptionalDataProto__.call(SwiftRuntime.toOptionalSegmentInstance(arg));
}
""",
diff --git a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift
index bdf00de18..a2b1fc9e3 100644
--- a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift
+++ b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift
@@ -52,8 +52,8 @@ struct SwiftSymbolTableSuite {
#expect(symbolTable.lookupType("Z", parent: nil) == nil)
}
- @Test(arguments: [JExtractGenerationMode.jni, .ffm])
- func resolveSelfModuleName(mode: JExtractGenerationMode) throws {
+ @Test
+ func resolveSelfModuleName() throws {
try assertOutput(
input: """
import Foundation
@@ -62,13 +62,13 @@ struct SwiftSymbolTableSuite {
public func fullyQualifiedType() -> MyModule.MyValue
public func fullyQualifiedType2() -> Foundation.Data
""",
- mode,
+ .jni,
.java,
swiftModuleName: "MyModule",
detectChunkByInitialLines: 1,
expectedChunks: [
"public static MyValue fullyQualifiedType(",
- "public static Data fullyQualifiedType2(",
+ "public static org.swift.swiftkit.core.foundation.Data fullyQualifiedType2(",
],
)
}
From 9a6f3edd12e3d650e0f54d1a0f16d3849c955b25 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 10:33:14 +0900
Subject: [PATCH 08/17] Fix benchmark code imports
---
.../src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java | 1 +
.../src/jmh/java/com/example/swift/JNIDataBenchmark.java | 1 +
2 files changed, 2 insertions(+)
diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java b/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
index 2ce5950f2..6cac287ff 100644
--- a/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
+++ b/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
@@ -17,6 +17,7 @@
import com.example.swift.MySwiftLibrary;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
+import org.swift.swiftkit.ffm.foundation.Data;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/JNIDataBenchmark.java b/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/JNIDataBenchmark.java
index 283f1f7c0..52b1d16b8 100644
--- a/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/JNIDataBenchmark.java
+++ b/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/JNIDataBenchmark.java
@@ -18,6 +18,7 @@
import org.openjdk.jmh.infra.Blackhole;
import org.swift.swiftkit.core.ClosableSwiftArena;
import org.swift.swiftkit.core.SwiftArena;
+import org.swift.swiftkit.core.foundation.Data;
import java.util.concurrent.TimeUnit;
From d9547652882b001a3e898b1f418441abd2f95010 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 11:02:15 +0900
Subject: [PATCH 09/17] swift format
---
...MSwift2JavaGenerator+JavaTranslation.swift | 26 +++++++++------
.../Foundation/Data+JNI.swift | 8 +++--
.../foundation/Data+FFM.swift | 8 ++---
Tests/JExtractSwiftTests/DateTests.swift | 32 +++++++++----------
4 files changed, 42 insertions(+), 32 deletions(-)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
index decc8a547..d4387c234 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
@@ -646,22 +646,28 @@ extension FFMSwift2JavaGenerator {
case .foundationData, .essentialsData:
return TranslatedParameter(
javaParameters: [
- JavaParameter(name: parameterName, type: .class(
- package: nil,
- name: "Optional",
- typeParameters: [.swiftkitFFMFoundationData]
- ))
+ JavaParameter(
+ name: parameterName,
+ type: .class(
+ package: nil,
+ name: "Optional",
+ typeParameters: [.swiftkitFFMFoundationData]
+ )
+ )
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
)
case .foundationDataProtocol, .essentialsDataProtocol:
return TranslatedParameter(
javaParameters: [
- JavaParameter(name: parameterName, type: .class(
- package: nil,
- name: "Optional",
- typeParameters: [.swiftkitFFMFoundationDataProtocol]
- ))
+ JavaParameter(
+ name: parameterName,
+ type: .class(
+ package: nil,
+ name: "Optional",
+ typeParameters: [.swiftkitFFMFoundationDataProtocol]
+ )
+ )
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
)
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
index 8110af8f3..2451ccd0b 100644
--- a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
@@ -60,7 +60,7 @@ public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J(en
fatalError("selfPointer memory address was null in call to \(#function)!")
}
return selfPointer$.pointee.withUnsafeBytes { buffer in
- return buffer.getJNIValue(in: environment)
+ buffer.getJNIValue(in: environment)
}
}
@@ -68,7 +68,11 @@ public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J(en
@used
#endif
@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J")
-public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jbyteArray? {
+public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J(
+ environment: UnsafeMutablePointer!,
+ thisClass: jclass,
+ selfPointer: jlong
+) -> jbyteArray? {
guard let env$ = environment else {
fatalError("Missing JNIEnv in downcall to \(#function)")
}
diff --git a/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift b/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
index 157abe53e..b7e2b6ab5 100644
--- a/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
+++ b/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
@@ -24,7 +24,7 @@ import Foundation
@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_Data")
public func swiftjava_getType_SwiftRuntimeFunctions_Data() -> UnsafeMutableRawPointer /* Any.Type */ {
- return unsafeBitCast(Data.self, to: UnsafeMutableRawPointer.self)
+ unsafeBitCast(Data.self, to: UnsafeMutableRawPointer.self)
}
@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count")
@@ -39,13 +39,13 @@ public func swiftjava_SwiftRuntimeFunctions_Data_init__(_ bytes_pointer: UnsafeR
@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_count$get")
public func swiftjava_SwiftRuntimeFunctions_Data_count$get(_ self: UnsafeRawPointer) -> Int {
- return self.assumingMemoryBound(to: Data.self).pointee.count
+ self.assumingMemoryBound(to: Data.self).pointee.count
}
@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__")
public func swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__(_ body: @convention(c) (UnsafeRawPointer?, Int) -> Void, _ self: UnsafeRawPointer) {
self.assumingMemoryBound(to: Data.self).pointee.withUnsafeBytes({ (_0) in
- return body(_0.baseAddress, _0.count)
+ body(_0.baseAddress, _0.count)
})
}
@@ -66,5 +66,5 @@ public func swiftjava_SwiftRuntimeFunctions_Data_copyBytes__(
@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_DataProtocol")
public func swiftjava_getType_SwiftRuntimeFunctions_DataProtocol() -> UnsafeMutableRawPointer /* Any.Type */ {
- return unsafeBitCast((any DataProtocol).self, to: UnsafeMutableRawPointer.self)
+ unsafeBitCast((any DataProtocol).self, to: UnsafeMutableRawPointer.self)
}
diff --git a/Tests/JExtractSwiftTests/DateTests.swift b/Tests/JExtractSwiftTests/DateTests.swift
index 13a1e59f1..7e694640c 100644
--- a/Tests/JExtractSwiftTests/DateTests.swift
+++ b/Tests/JExtractSwiftTests/DateTests.swift
@@ -32,11 +32,11 @@ struct DateTests {
.java,
detectChunkByInitialLines: 1,
expectedChunks: [
- """
- public static void acceptDate(org.swift.swiftkit.core.foundation.Date date) {
- SwiftModule.$acceptDate(date.$memoryAddress());
- }
- """
+ """
+ public static void acceptDate(org.swift.swiftkit.core.foundation.Date date) {
+ SwiftModule.$acceptDate(date.$memoryAddress());
+ }
+ """
]
)
@@ -46,10 +46,10 @@ struct DateTests {
.swift,
detectChunkByInitialLines: 1,
expectedChunks: [
- """
- @_cdecl("Java_com_example_swift_SwiftModule__00024acceptDate__J")
- public func Java_com_example_swift_SwiftModule__00024acceptDate__J(environment: UnsafeMutablePointer!, thisClass: jclass, date: jlong) {
- """
+ """
+ @_cdecl("Java_com_example_swift_SwiftModule__00024acceptDate__J")
+ public func Java_com_example_swift_SwiftModule__00024acceptDate__J(environment: UnsafeMutablePointer!, thisClass: jclass, date: jlong) {
+ """
]
)
}
@@ -67,9 +67,9 @@ struct DateTests {
.jni,
.java,
expectedChunks: [
- """
- public static org.swift.swiftkit.core.foundation.Date returnDate(SwiftArena swiftArena) {
- """
+ """
+ public static org.swift.swiftkit.core.foundation.Date returnDate(SwiftArena swiftArena) {
+ """
],
)
@@ -78,10 +78,10 @@ struct DateTests {
.jni,
.swift,
expectedChunks: [
- """
- @_cdecl("Java_com_example_swift_SwiftModule__00024returnDate__")
- public func Java_com_example_swift_SwiftModule__00024returnDate__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
- """
+ """
+ @_cdecl("Java_com_example_swift_SwiftModule__00024returnDate__")
+ public func Java_com_example_swift_SwiftModule__00024returnDate__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
+ """
]
)
}
From f377d1c2d69a276c7acb904a34b056c21b26141c Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 11:20:03 +0900
Subject: [PATCH 10/17] simple collapling
---
...FFMSwift2JavaGenerator+JavaBindingsPrinting.swift | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
index 48cf4c331..1385894d3 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -621,14 +621,10 @@ extension FFMSwift2JavaGenerator {
func renderMemoryLayoutValue(for javaType: JavaType) -> String {
if let layout = ForeignValueLayout(javaType: javaType) {
return layout.description
- } else if case .class(let package, name: let customClass, _) = javaType {
- let type =
- if let package {
- "\(package).\(customClass)"
- } else {
- customClass
- }
- return ForeignValueLayout(customType: type).description
+ } else if case .class(.some(let package), name: let customClass, _) = javaType {
+ return ForeignValueLayout(customType: "\(package).\(customClass)").description
+ } else if case .class(.none, name: let customClass, _) = javaType {
+ return ForeignValueLayout(customType: customClass).description
} else {
fatalError("renderMemoryLayoutValue not supported for \(javaType)")
}
From ab3e202e116c099080d7539b72a16e0e1a114e72 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 11:43:33 +0900
Subject: [PATCH 11/17] Add JavaType.optional utility function
---
.../FFMSwift2JavaGenerator+JavaTranslation.swift | 14 +++-----------
.../JNISwift2JavaGenerator+JavaTranslation.swift | 8 ++++----
.../JExtractSwiftLib/JavaTypes/JavaType+JDK.swift | 5 +++++
Tests/JExtractSwiftTests/DataImportTests.swift | 2 +-
Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift | 6 +++---
.../JNI/JNIGenericCombinationTests.swift | 4 ++--
.../JExtractSwiftTests/JNI/JNIOptionalTests.swift | 2 +-
Tests/JExtractSwiftTests/OptionalImportTests.swift | 2 +-
8 files changed, 20 insertions(+), 23 deletions(-)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
index d4387c234..e4363b7a4 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
@@ -648,11 +648,7 @@ extension FFMSwift2JavaGenerator {
javaParameters: [
JavaParameter(
name: parameterName,
- type: .class(
- package: nil,
- name: "Optional",
- typeParameters: [.swiftkitFFMFoundationData]
- )
+ type: .optional(.swiftkitFFMFoundationData)
)
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
@@ -662,11 +658,7 @@ extension FFMSwift2JavaGenerator {
javaParameters: [
JavaParameter(
name: parameterName,
- type: .class(
- package: nil,
- name: "Optional",
- typeParameters: [.swiftkitFFMFoundationDataProtocol]
- )
+ type: .optional(.swiftkitFFMFoundationDataProtocol)
)
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
@@ -679,7 +671,7 @@ extension FFMSwift2JavaGenerator {
let translatedTy = try self.translate(swiftType: swiftType)
return TranslatedParameter(
javaParameters: [
- JavaParameter(name: parameterName, type: .class(package: nil, name: "Optional", typeParameters: [translatedTy]))
+ JavaParameter(name: parameterName, type: .optional(translatedTy))
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
)
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
index 733cbac43..f5ce801cc 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
@@ -176,7 +176,7 @@ extension JNISwift2JavaGenerator {
),
parameters: [],
resultType: TranslatedResult(
- javaType: .class(package: nil, name: "Optional", typeParameters: [.class(package: nil, name: caseName)]),
+ javaType: .optional(.class(package: nil, name: caseName)),
outParameters: conversions.flatMap(\.translated.outParameters),
conversion: enumCase.parameters.isEmpty
? constructRecordConversion
@@ -886,7 +886,7 @@ extension JNISwift2JavaGenerator {
return TranslatedParameter(
parameter: JavaParameter(
name: parameterName,
- type: .class(package: nil, name: "Optional", typeParameters: [javaType]),
+ type: .optional(javaType),
annotations: parameterAnnotations,
),
conversion: .method(
@@ -1077,7 +1077,7 @@ extension JNISwift2JavaGenerator {
genericParameters: genericParameters,
genericRequirements: genericRequirements,
)
- return .class(package: "java.util", name: "Optional", typeParameters: [wrappedType])
+ return .optional(wrappedType)
case .array:
guard let elementType = nominalType.genericArguments?.first else {
@@ -1361,7 +1361,7 @@ extension JNISwift2JavaGenerator {
.void
}
- let returnType = JavaType.class(package: nil, name: "Optional", typeParameters: [javaType])
+ let returnType = JavaType.optional(javaType)
return TranslatedResult(
javaType: returnType,
annotations: parameterAnnotations,
diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
index 6790c5af9..246f8a8b1 100644
--- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
+++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
@@ -45,6 +45,11 @@ extension JavaType {
.class(package: "java.lang", name: "Object")
}
+ /// The description of the type java.util.Optional..
+ static func optional(_ T: JavaType) -> JavaType {
+ .class(package: "java.util", name: "Optional", typeParameters: [T])
+ }
+
/// The description of the type java.util.concurrent.CompletableFuture
static func completableFuture(_ T: JavaType) -> JavaType {
.class(package: "java.util.concurrent", name: "CompletableFuture", typeParameters: [T.boxedType])
diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift
index c2ce81ca5..42149c5ee 100644
--- a/Tests/JExtractSwiftTests/DataImportTests.swift
+++ b/Tests/JExtractSwiftTests/DataImportTests.swift
@@ -267,7 +267,7 @@ final class DataImportTests {
* public func receiveDataProtocol(dat: some DataProtocol, dat2: T?)
* }
*/
- public static void receiveDataProtocol(org.swift.swiftkit.ffm.foundation.Data dat, Optional dat2) {
+ public static void receiveDataProtocol(org.swift.swiftkit.ffm.foundation.Data dat, java.util.Optional dat2) {
swiftjava_SwiftModule_receiveDataProtocol_dat_dat2.call(dat.$memorySegment(), SwiftRuntime.toOptionalSegmentInstance(dat2));
}
""",
diff --git a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift
index e09c215ca..0f3db0ca0 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift
@@ -268,7 +268,7 @@ struct JNIEnumTests {
detectChunkByInitialLines: 1,
expectedChunks: [
"""
- public Optional getAsFirst() {
+ public java.util.Optional getAsFirst() {
if (getDiscriminator() != Discriminator.FIRST) {
return Optional.empty();
}
@@ -276,7 +276,7 @@ struct JNIEnumTests {
}
""",
"""
- public Optional getAsSecond() {
+ public java.util.Optional getAsSecond() {
if (getDiscriminator() != Discriminator.SECOND) {
return Optional.empty();
}
@@ -285,7 +285,7 @@ struct JNIEnumTests {
}
""",
"""
- public Optional getAsThird() {
+ public java.util.Optional getAsThird() {
if (getDiscriminator() != Discriminator.THIRD) {
return Optional.empty();
}
diff --git a/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift b/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift
index 57651e1e1..45b4cb2ec 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift
@@ -55,7 +55,7 @@ struct JNIGenericCombinationTests {
detectChunkByInitialLines: 2,
expectedChunks: [
"""
- public static Optional> makeStringIDOptional(java.lang.String value, SwiftArena swiftArena) {
+ public static java.util.Optional> makeStringIDOptional(java.lang.String value, SwiftArena swiftArena) {
byte[] result$_discriminator$ = new byte[1];
org.swift.swiftkit.core._OutSwiftGenericInstance resultWrapped$ = new org.swift.swiftkit.core._OutSwiftGenericInstance();
SwiftModule.$makeStringIDOptional(value, result$_discriminator$, resultWrapped$);
@@ -113,7 +113,7 @@ struct JNIGenericCombinationTests {
detectChunkByInitialLines: 2,
expectedChunks: [
"""
- public static void takeStringIDOptional(Optional> value) {
+ public static void takeStringIDOptional(java.util.Optional> value) {
SwiftModule.$takeStringIDOptional(value.map(MyID::$memoryAddress).orElse(0L));
}
""",
diff --git a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift
index 728165bf8..d01c4b103 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift
@@ -155,7 +155,7 @@ struct JNIOptionalTests {
* public func optionalClass(_ arg: MyClass?) -> MyClass?
* }
*/
- public static Optional optionalClass(Optional arg, SwiftArena swiftArena) {
+ public static java.util.Optional optionalClass(java.util.Optional arg, SwiftArena swiftArena) {
byte[] result$_discriminator$ = new byte[1];
long result$ = SwiftModule.$optionalClass(arg.map(MyClass::$memoryAddress).orElse(0L), result$_discriminator$);
return (result$_discriminator$[0] == 1) ? Optional.of(MyClass.wrapMemoryAddressUnsafe(result$, swiftArena)) : Optional.empty();
diff --git a/Tests/JExtractSwiftTests/OptionalImportTests.swift b/Tests/JExtractSwiftTests/OptionalImportTests.swift
index ea20272e3..60473bd3a 100644
--- a/Tests/JExtractSwiftTests/OptionalImportTests.swift
+++ b/Tests/JExtractSwiftTests/OptionalImportTests.swift
@@ -146,7 +146,7 @@ final class OptionalImportTests {
* public func receiveOptionalDataProto(_ arg: (some DataProtocol)?)
* }
*/
- public static void receiveOptionalDataProto(Optional arg) {
+ public static void receiveOptionalDataProto(java.util.Optional arg) {
swiftjava_SwiftModule_receiveOptionalDataProto__.call(SwiftRuntime.toOptionalSegmentInstance(arg));
}
""",
From c4eaf38f1be62e23bdcc45bc8bd810267e4d8c27 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 12:50:02 +0900
Subject: [PATCH 12/17] Make --single-type available in JNI
---
...ift2JavaGenerator+SwiftThunkPrinting.swift | 1 +
...t2JavaGenerator+JavaBindingsPrinting.swift | 35 ++++++++++++-------
...ift2JavaGenerator+SwiftThunkPrinting.swift | 35 ++++++++++++-------
3 files changed, 47 insertions(+), 24 deletions(-)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift
index fe7372759..40cab0646 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift
@@ -71,6 +71,7 @@ extension FFMSwift2JavaGenerator {
// === All types
// We have to write all types to their corresponding output file that matches the file they were declared in,
// because otherwise SwiftPM plugins will not pick up files apropriately -- we expect 1 output +SwiftJava.swift file for every input.
+
let filteredTypes: [String: ImportedNominalType]
if let singleType = config.singleType {
filteredTypes = self.analysis.importedTypes.filter { $0.key == singleType }
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
index 833aabbcd..cef345ca7 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -42,13 +42,21 @@ extension JNISwift2JavaGenerator {
}
package func writeExportedJavaSources(_ printer: inout CodePrinter) throws {
- let importedTypes = analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key })
+ let typesToExport: [(key: String, value: ImportedNominalType)]
+ if let singleType = config.singleType {
+ typesToExport = analysis.importedTypes
+ .filter { $0.key == singleType }
+ .sorted(by: { $0.key < $1.key })
+ } else {
+ typesToExport = analysis.importedTypes
+ .sorted(by: { $0.key < $1.key })
+ }
var exportedFileNames: OrderedSet = []
// Each parent type goes into its own file
// any nested types are printed inside the body as `static class`
- for (_, ty) in importedTypes.filter({ _, type in type.parent == nil }) {
+ for (_, ty) in typesToExport.filter({ _, type in type.parent == nil }) {
let filename = "\(ty.effectiveJavaSimpleName).java"
logger.debug("Printing contents: \(filename)")
printImportedNominal(&printer, ty)
@@ -63,17 +71,20 @@ extension JNISwift2JavaGenerator {
}
}
- let filename = "\(self.swiftModuleName).java"
- logger.trace("Printing module class: \(filename)")
- printModule(&printer)
+ // Skip the module-level .swift file when generating for a single type
+ if config.singleType == nil {
+ let filename = "\(self.swiftModuleName).java"
+ logger.trace("Printing module class: \(filename)")
+ printModule(&printer)
- if let outputFile = try printer.writeContents(
- outputDirectory: javaOutputDirectory,
- javaPackagePath: javaPackagePath,
- filename: filename,
- ) {
- exportedFileNames.append(outputFile.path(percentEncoded: false))
- logger.info("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))")
+ if let outputFile = try printer.writeContents(
+ outputDirectory: javaOutputDirectory,
+ javaPackagePath: javaPackagePath,
+ filename: filename,
+ ) {
+ exportedFileNames.append(outputFile.path(percentEncoded: false))
+ logger.info("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))")
+ }
}
// Write java sources list file
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
index 24c106c01..a47486708 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
@@ -57,24 +57,35 @@ extension JNISwift2JavaGenerator {
let moduleFilename = "\(moduleFilenameBase).swift"
do {
- logger.trace("Printing swift module class: \(moduleFilename)")
-
- try printGlobalSwiftThunkSources(&printer)
-
- if let outputFile = try printer.writeContents(
- outputDirectory: self.swiftOutputDirectory,
- javaPackagePath: nil,
- filename: moduleFilename,
- ) {
- logger.info("Generated: \(moduleFilenameBase.bold).swift (at \(outputFile.absoluteString))")
- self.expectedOutputSwiftFileNames.remove(moduleFilename)
+ // Skip the module-level .swift file when generating for a single type
+ if config.singleType == nil {
+ logger.trace("Printing swift module class: \(moduleFilename)")
+
+ try printGlobalSwiftThunkSources(&printer)
+
+ if let outputFile = try printer.writeContents(
+ outputDirectory: self.swiftOutputDirectory,
+ javaPackagePath: nil,
+ filename: moduleFilename,
+ ) {
+ logger.info("Generated: \(moduleFilenameBase.bold).swift (at \(outputFile.absoluteString))")
+ self.expectedOutputSwiftFileNames.remove(moduleFilename)
+ }
}
// === All types
// We have to write all types to their corresponding output file that matches the file they were declared in,
// because otherwise SwiftPM plugins will not pick up files apropriately -- we expect 1 output +SwiftJava.swift file for every input.
+
+ let filteredTypes: [String: ImportedNominalType]
+ if let singleType = config.singleType {
+ filteredTypes = self.analysis.importedTypes.filter { $0.key == singleType }
+ } else {
+ filteredTypes = self.analysis.importedTypes
+ }
+
for group: (key: String, value: [Dictionary.Element]) in Dictionary(
- grouping: self.analysis.importedTypes,
+ grouping: filteredTypes,
by: { $0.value.sourceFilePath },
) {
logger.warning("Writing types in file group: \(group.key): \(group.value.map(\.key))")
From a040322287ff5094acba92adb88282fe82f34c92 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 12:50:10 +0900
Subject: [PATCH 13/17] Reuse the generation script
---
Sources/FakeFoundation/Data.swift | 26 +++
Sources/FakeFoundation/Date.swift | 27 +++
...FMSwift2JavaGenerator+FoundationData.swift | 166 ++++++++++++++++++
.../FFM/FFMSwift2JavaGenerator.swift | 17 ++
...t2JavaGenerator+JavaBindingsPrinting.swift | 131 ++++++++++++++
...ift2JavaGenerator+SwiftThunkPrinting.swift | 62 +++++++
scripts/swiftkit-jni-generate-bindings.sh | 52 ++++++
7 files changed, 481 insertions(+)
create mode 100644 Sources/FakeFoundation/Data.swift
create mode 100644 Sources/FakeFoundation/Date.swift
create mode 100644 Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift
create mode 100755 scripts/swiftkit-jni-generate-bindings.sh
diff --git a/Sources/FakeFoundation/Data.swift b/Sources/FakeFoundation/Data.swift
new file mode 100644
index 000000000..5fd160dd0
--- /dev/null
+++ b/Sources/FakeFoundation/Data.swift
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public struct Data: DataProtocol {
+ public init(bytes: UnsafeRawPointer, count: Int)
+ public init(_ bytes: [UInt8])
+ public var count: Int { get }
+ public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
+}
diff --git a/Sources/FakeFoundation/Date.swift b/Sources/FakeFoundation/Date.swift
new file mode 100644
index 000000000..ee18b8afc
--- /dev/null
+++ b/Sources/FakeFoundation/Date.swift
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public struct Date {
+ /// The interval between the date object and 00:00:00 UTC on 1 January 1970.
+ public var timeIntervalSince1970: Double { get }
+
+ /// Returns a `Date` initialized relative to 00:00:00 UTC on 1 January 1970 by a given number of seconds.
+ public init(timeIntervalSince1970: Double)
+}
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift
new file mode 100644
index 000000000..7dd054f22
--- /dev/null
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift
@@ -0,0 +1,166 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+import CodePrinting
+import SwiftJavaConfigurationShared
+import SwiftJavaJNICore
+import SwiftSyntax
+import SwiftSyntaxBuilder
+
+import struct Foundation.URL
+
+extension FFMSwift2JavaGenerator {
+
+ /// Print Java helper methods for Foundation.Data type
+ package func printFoundationDataHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
+ let typeName = decl.swiftNominal.name
+ let thunkNameCopyBytes = "swiftjava_\(swiftModuleName)_\(typeName)_copyBytes__"
+
+ printer.printSeparator("\(typeName) helper methods")
+
+ // This is primarily here for API parity with the JNI version and easier discovery
+ printer.print(
+ """
+ /**
+ * Creates a new Swift {@link \(typeName)} instance from a byte array.
+ *
+ * @param bytes The byte array to copy into the \(typeName)
+ * @param arena The arena for memory management
+ * @return A new \(typeName) instance containing a copy of the bytes
+ */
+ public static \(typeName) fromByteArray(byte[] bytes, AllocatingSwiftArena arena) {
+ Objects.requireNonNull(bytes, "bytes cannot be null");
+ return \(typeName).init(bytes, arena);
+ }
+ """
+ )
+
+ // TODO: Implement a fromByteBuffer as well
+
+ // Print the descriptor class for copyBytes native call using the shared helper
+ let copyBytesCFunc = CFunction(
+ resultType: .void,
+ name: thunkNameCopyBytes,
+ parameters: [
+ CParameter(name: "self", type: .qualified(const: true, volatile: false, type: .pointer(.void))),
+ CParameter(name: "destination", type: .pointer(.void)),
+ CParameter(name: "count", type: .integral(.ptrdiff_t)),
+ ],
+ isVariadic: false
+ )
+ printJavaBindingDescriptorClass(&printer, copyBytesCFunc)
+
+ printer.print(
+ """
+ /**
+ * Copies the contents of this \(typeName) to a new {@link MemorySegment}.
+ *
+ * This is the most efficient way to access \(typeName) bytes from Java when you don't
+ * need a {@code byte[]}. The returned segment is valid for the lifetime of the arena.
+ *
+ * Copy count: 1 (Swift Data -> MemorySegment)
+ *
+ * @param arena The arena to allocate the segment in
+ * @return A MemorySegment containing a copy of this \(typeName)'s bytes
+ */
+ public MemorySegment toMemorySegment(AllocatingSwiftArena arena) {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return MemorySegment.NULL;
+ MemorySegment segment = arena.allocate(count);
+ \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
+ return segment;
+ }
+ """
+ )
+
+ printer.print(
+ """
+ /**
+ * Copies the contents of this \(typeName) to a new {@link ByteBuffer}.
+ *
+ * The returned {@link java.nio.ByteBuffer} is a view over native memory and is valid for the
+ * lifetime of the arena. This avoids an additional copy to the Java heap.
+ *
+ *
Copy count: 1 (Swift Data -> native memory (managed by passed arena), then zero-copy view)
+ *
+ * @param arena The arena to allocate the underlying memory in
+ * @return A ByteBuffer view of the copied bytes
+ */
+ public java.nio.ByteBuffer toByteBuffer(AllocatingSwiftArena arena) {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return java.nio.ByteBuffer.allocate(0);
+ MemorySegment segment = arena.allocate(count);
+ \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
+ return segment.asByteBuffer();
+ }
+ """
+ )
+
+ printer.print(
+ """
+ /**
+ * Copies the contents of this \(typeName) to a new byte array.
+ * The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
+ *
+ *
Copy count: 2 (Swift Data -> MemorySegment -> byte[])
+ *
+ *
For better performance when you can work with {@link MemorySegment} or
+ * {@link java.nio.ByteBuffer}, prefer {@link #toMemorySegment} or {@link #toByteBuffer}.
+ *
+ * @param arena The arena to use for temporary native memory allocation
+ * @return A byte array containing a copy of this \(typeName)'s bytes
+ */
+ public byte[] toByteArray(AllocatingSwiftArena arena) {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return new byte[0];
+ MemorySegment segment = arena.allocate(count);
+ \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
+ return segment.toArray(ValueLayout.JAVA_BYTE);
+ }
+ """
+ )
+
+ printer.print(
+ """
+ /**
+ * Copies the contents of this \(typeName) to a new byte array.
+ * The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
+ *
+ * This is a convenience method that creates a temporary arena for the copy.
+ * For repeated calls, prefer {@link #toByteArray(AllocatingSwiftArena)} to reuse an arena.
+ *
+ *
Copy count: 2 (Swift Data -> MemorySegment -> byte[])
+ *
+ *
For better performance when you can work with {@link MemorySegment} or
+ * {@link java.nio.ByteBuffer}, prefer {@link #toMemorySegment} or {@link #toByteBuffer}.
+ *
+ * @return A byte array containing a copy of this \(typeName)'s bytes
+ */
+ public byte[] toByteArray() {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return new byte[0];
+ try (var arena = Arena.ofConfined()) {
+ MemorySegment segment = arena.allocate(count);
+ \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
+ return segment.toArray(ValueLayout.JAVA_BYTE);
+ }
+ }
+ """
+ )
+ }
+}
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
index 4572316c3..41c063048 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
@@ -328,6 +328,9 @@ extension FFMSwift2JavaGenerator {
printFunctionDowncallMethods(&printer, funcDecl)
}
+ // Special helper methods for known types (e.g. Data)
+ printSpecificTypeHelpers(&printer, decl)
+
if let printSpecialPostExtras = self.getSpecialNominalPostMembersPrinting(decl) {
printSpecialPostExtras(&printer)
} else {
@@ -552,6 +555,20 @@ extension FFMSwift2JavaGenerator {
)
}
+ /// Print special helper methods for known types like Foundation.Data
+ func printSpecificTypeHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
+ guard let knownType = decl.swiftNominal.knownTypeKind else {
+ return
+ }
+
+ switch knownType {
+ case .foundationData, .essentialsData:
+ printFoundationDataHelpers(&printer, decl)
+ default:
+ break
+ }
+ }
+
/// Print the `fetchDescription` static helper for SwiftJavaError.
/// This calls the `errorDescription()` downcall to get the error message
/// for the super constructor
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
index cef345ca7..7bcbd13a5 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -325,6 +325,8 @@ extension JNISwift2JavaGenerator {
printer.println()
}
+ printSpecificTypeHelpers(&printer, decl)
+
printTypeMetadataAddressFunction(&printer, decl)
printer.println()
@@ -345,6 +347,22 @@ extension JNISwift2JavaGenerator {
}
}
+ /// Prints helpers for specific types like `Foundation.Date`
+ private func printSpecificTypeHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
+ guard let knownType = decl.swiftNominal.knownTypeKind else { return }
+
+ switch knownType {
+ case .foundationDate, .essentialsDate:
+ printFoundationDateHelpers(&printer, decl)
+
+ case .foundationData, .essentialsData:
+ printFoundationDataHelpers(&printer, decl)
+
+ default:
+ break
+ }
+ }
+
private func printHeader(_ printer: inout CodePrinter) {
printer.print(
"""
@@ -825,4 +843,117 @@ extension JNISwift2JavaGenerator {
}
}
}
+
+ private func printFoundationDateHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
+ printer.print(
+ """
+ /**
+ * Converts this wrapped date to a Java {@link java.time.Instant}.
+ *
+ * This method constructs the {@code Instant} using the underlying {@code double} value
+ * representing seconds since the Unix Epoch (January 1, 1970).
+ *
+ *
+ * @return A {@code java.time.Instant} derived from the floating-point timestamp.
+ */
+ public java.time.Instant toInstant() {
+ long seconds = (long) this.getTimeIntervalSince1970();
+ long nanos = Math.round((this.getTimeIntervalSince1970() - seconds) * 1_000_000_000);
+ return java.time.Instant.ofEpochSecond(seconds, nanos);
+ }
+ """
+ )
+ printer.println()
+ printer.print(
+ """
+ /**
+ * Initializes a Swift {@code Foundation.Date} from a Java {@link java.time.Instant}.
+ *
+ * Warning: Precision Loss
+ *
+ * The input precision will be degraded.
+ *
+ *
+ * Java's {@code Instant} stores time with nanosecond precision (9 decimal places).
+ * However, this class stores time as a 64-bit floating-point value.
+ *
+ *
+ * This leaves enough capacity for microsecond precision (approx. 6 decimal places).
+ *
+ *
+ * Consequently, the last ~3 digits of the {@code Instant}'s nanosecond field will be
+ * truncated or subjected to rounding errors during conversion.
+ *
+ *
+ * @param instant The source timestamp to convert.
+ * @return A date derived from the input instant with microsecond precision.
+ */
+ public static Date fromInstant(java.time.Instant instant, SwiftArena swiftArena) {
+ Objects.requireNonNull(instant, "Instant cannot be null");
+ double timeIntervalSince1970 = instant.getEpochSecond() + (instant.getNano() / 1_000_000_000.0);
+ return Date.init(timeIntervalSince1970, swiftArena);
+ }
+ """
+ )
+ }
+
+ private func printFoundationDataHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
+ printer.print(
+ """
+ /**
+ * Creates a new Swift @{link Data} instance from a byte array.
+ *
+ * @param bytes The byte array to copy into the Data
+ * @param swiftArena The arena for memory management
+ * @return A new Data instance containing a copy of the bytes
+ */
+ public static Data fromByteArray(byte[] bytes, SwiftArena swiftArena) {
+ Objects.requireNonNull(bytes, "bytes cannot be null");
+ return Data.init(bytes, swiftArena);
+ }
+ """
+ )
+
+ printer.print(
+ """
+ /**
+ * Copies the contents of this Data to a new byte array.
+ *
+ * This is a relatively efficient implementation, which avoids native array copies,
+ * however it will still perform a copy of the data onto the JVM heap, so use this
+ * only when necessary.
+ *
+ * When utmost performance is necessary, you may want to investigate the FFM mode
+ * of jextract which is able to map memory more efficiently.
+ *
+ * @return A byte array containing a copy of this Data's bytes
+ */
+ public byte[] toByteArray() {
+ return $toByteArray(this.$memoryAddress());
+ }
+ """
+ )
+
+ printer.print(
+ """
+ private static native byte[] $toByteArray(long selfPointer);
+
+ /**
+ * Copies the contents of this Data to a new byte array.
+ *
+ * @deprecated Prefer using the `toByteArray` method as it is more performant.
+ * This implementation uses a naive conversion path from native bytes into jbytes
+ * and then copying them onto the jvm heap.
+ *
+ * @return A byte array containing a copy of this Data's bytes
+ */
+ @Deprecated(forRemoval = true)
+ public byte[] toByteArrayIndirectCopy() {
+ return $toByteArrayIndirectCopy(this.$memoryAddress());
+ }
+
+ private static native byte[] $toByteArrayIndirectCopy(long selfPointer);
+ """
+ )
+ }
}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
index a47486708..233a95df9 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
@@ -358,6 +358,7 @@ extension JNISwift2JavaGenerator {
printer.println()
}
+ printSpecificTypeThunks(&printer, type)
printTypeMetadataAddressThunk(&printer, type)
printer.println()
}
@@ -866,6 +867,67 @@ extension JNISwift2JavaGenerator {
}
}
+ /// Prints thunks for specific known types like Foundation.Date, Foundation.Data
+ private func printSpecificTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) {
+ guard let knownType = type.swiftNominal.knownTypeKind else { return }
+
+ switch knownType {
+ case .foundationData, .essentialsData:
+ printFoundationDataThunks(&printer, type)
+ printer.println()
+
+ default:
+ break
+ }
+ }
+
+ /// Prints Swift thunks for Foundation.Data helper methods
+ private func printFoundationDataThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) {
+ let selfPointerParam = JavaParameter(name: "selfPointer", type: .long)
+ let parentName = type.qualifiedName
+
+ // Rebind the memory instead of converting, and set the memory directly using 'jniSetArrayRegion' from the buffer
+ printCDecl(
+ &printer,
+ javaMethodName: "$toByteArray",
+ parentName: type.effectiveJavaName,
+ parameters: [
+ selfPointerParam
+ ],
+ resultType: .array(.byte),
+ ) { printer in
+ let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, swiftParentName: parentName, selfPointerParam)
+
+ printer.print(
+ """
+ return \(selfVar).pointee.withUnsafeBytes { buffer in
+ return buffer.getJNIValue(in: environment)
+ }
+ """
+ )
+ }
+
+ // Legacy API, also to compare with as a baseline, we could remove it
+ printCDecl(
+ &printer,
+ javaMethodName: "$toByteArrayIndirectCopy",
+ parentName: type.effectiveJavaName,
+ parameters: [
+ selfPointerParam
+ ],
+ resultType: .array(.byte),
+ ) { printer in
+ let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, swiftParentName: parentName, selfPointerParam)
+
+ printer.print(
+ """
+ // This is a double copy, we need to initialize the array and then copy into a JVM array in getJNIValue
+ return [UInt8](\(selfVar).pointee).getJNIValue(in: environment)
+ """
+ )
+ }
+ }
+
private func printFunctionOpenerCall(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
guard let translatedDecl = self.translatedDecl(for: decl) else {
fatalError("Cannot print function opener for a function that can't be translated: \(decl)")
diff --git a/scripts/swiftkit-jni-generate-bindings.sh b/scripts/swiftkit-jni-generate-bindings.sh
new file mode 100755
index 000000000..7af973949
--- /dev/null
+++ b/scripts/swiftkit-jni-generate-bindings.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+##===----------------------------------------------------------------------===##
+##
+## This source file is part of the Swift.org open source project
+##
+## Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+## Licensed under Apache License v2.0
+##
+## See LICENSE.txt for license information
+## See CONTRIBUTORS.txt for the list of Swift.org project authors
+##
+## SPDX-License-Identifier: Apache-2.0
+##
+##===----------------------------------------------------------------------===##
+
+# Regenerate FFM bindings for types in SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/
+#
+# Run from the swift-java repository root:
+# ./scripts/swiftkit-ffm-generate-bindings.sh
+
+set -euo pipefail
+
+REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
+
+JAVA_OUTPUT="${REPO_ROOT}/SwiftKitCore/src/main/java"
+JAVA_PACKAGE="org.swift.swiftkit.core.foundation"
+
+# Declare types to generate: SWIFT_MODULE SINGLE_TYPE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
+TYPES=(
+ "Foundation Data Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/foundation"
+ "Foundation Date Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/foundation"
+)
+
+for entry in "${TYPES[@]}"; do
+ read -r MODULE SINGLE_TYPE INPUT_SWIFT OUTPUT_SWIFT <<< "$entry"
+
+ echo "==> Generating ${INPUT_SWIFT} ${SINGLE_TYPE}..."
+
+ xcrun swift run swift-java jextract \
+ --mode jni \
+ --single-type "$SINGLE_TYPE" \
+ --swift-module "$MODULE" \
+ --input-swift "${REPO_ROOT}/${INPUT_SWIFT}" \
+ --output-swift "${REPO_ROOT}/${OUTPUT_SWIFT}" \
+ --output-java "$JAVA_OUTPUT" \
+ --java-package "$JAVA_PACKAGE"
+
+ echo " Swift thunks: ${OUTPUT_SWIFT}/"
+ echo " Java output: SwiftKitCore/src/main/java/$(echo "$JAVA_PACKAGE" | tr '.' '/')/"
+done
+
+echo "==> Done."
From 8ee8976a0144e36786330a97a1a58de959890798 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 15:17:29 +0900
Subject: [PATCH 14/17] Update generator logic for internal module
---
Sources/FakeFoundation/DataProtocol.swift | 21 ++++
...ift2JavaGenerator+SwiftThunkPrinting.swift | 30 +++--
.../FFM/FFMSwift2JavaGenerator.swift | 16 ++-
...t2JavaGenerator+JavaBindingsPrinting.swift | 20 ++--
...ift2JavaGenerator+SwiftThunkPrinting.swift | 46 ++++----
.../Foundation/Data+JNI.swift | 86 ---------------
.../Foundation/Data+SwiftJava.swift | 91 ++++++++++++++++
.../Foundation/DataProtocol+SwiftJava.swift | 17 +++
.../Foundation/Date+JNI.swift | 47 --------
.../Foundation/Date+SwiftJava.swift | 55 ++++++++++
.../{Data+FFM.swift => Data+SwiftJava.swift} | 23 +---
.../foundation/DataProtocol+SwiftJava.swift | 17 +++
.../generated/SwiftJavaError+SwiftJava.swift | 1 -
.../swift/swiftkit/core/foundation/Data.java | 88 +++++++--------
.../core/foundation/DataProtocol.java | 24 ++--
.../swift/swiftkit/core/foundation/Date.java | 67 +++++-------
.../swift/swiftkit/ffm/foundation/Data.java | 103 +++++++-----------
.../swiftkit/ffm/foundation/DataProtocol.java | 31 ++----
.../generated/SwiftJavaErrorException.java | 2 +-
scripts/swiftkit-ffm-generate-bindings.sh | 11 +-
scripts/swiftkit-jni-generate-bindings.sh | 5 +-
21 files changed, 397 insertions(+), 404 deletions(-)
create mode 100644 Sources/FakeFoundation/DataProtocol.swift
delete mode 100644 Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift
delete mode 100644 Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift
rename Sources/SwiftRuntimeFunctions/foundation/{Data+FFM.swift => Data+SwiftJava.swift} (70%)
create mode 100644 Sources/SwiftRuntimeFunctions/foundation/DataProtocol+SwiftJava.swift
diff --git a/Sources/FakeFoundation/DataProtocol.swift b/Sources/FakeFoundation/DataProtocol.swift
new file mode 100644
index 000000000..d5a02d423
--- /dev/null
+++ b/Sources/FakeFoundation/DataProtocol.swift
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public protocol DataProtocol {}
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift
index 40cab0646..99b2640f3 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift
@@ -93,14 +93,13 @@ extension FFMSwift2JavaGenerator {
let filename = "\(inputFileName)".replacing(".swift", with: "+SwiftJava.swift")
// Print file header before all type thunks
- printer.print(
- """
- // Generated by swift-java
-
- import SwiftRuntimeFunctions
+ printer.print("// Generated by swift-java")
+ printer.println()
+ if !group.value.allSatisfy({ $0.value.swiftNominal.moduleName == "SwiftRuntimeFunctions" }) {
+ printer.print("import SwiftRuntimeFunctions")
+ }
+ printer.println()
- """
- )
self.lookupContext.symbolTable.printImportedModules(&printer)
for ty in importedTypesForThisFile {
@@ -264,16 +263,15 @@ struct SwiftThunkTranslator {
/// Render special thunks for known types like Foundation.Data
func renderSpecificTypeThunks(_ nominal: ImportedNominalType) -> [DeclSyntax] {
- guard let knownType = nominal.swiftNominal.knownTypeKind else {
- return []
- }
-
- switch knownType {
- case .foundationData, .essentialsData:
- return renderFoundationDataThunks(nominal)
- default:
- return []
+ if nominal.swiftNominal.moduleName == "SwiftRuntimeFunctions" {
+ switch nominal.swiftNominal.qualifiedName {
+ case "Data":
+ return renderFoundationDataThunks(nominal)
+ default:
+ break
+ }
}
+ return []
}
/// Render Swift thunks for Foundation.Data helper methods
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
index 41c063048..8427208c3 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
@@ -557,15 +557,13 @@ extension FFMSwift2JavaGenerator {
/// Print special helper methods for known types like Foundation.Data
func printSpecificTypeHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- guard let knownType = decl.swiftNominal.knownTypeKind else {
- return
- }
-
- switch knownType {
- case .foundationData, .essentialsData:
- printFoundationDataHelpers(&printer, decl)
- default:
- break
+ if decl.swiftNominal.moduleName == "SwiftRuntimeFunctions" {
+ switch decl.swiftNominal.qualifiedName {
+ case "Data":
+ printFoundationDataHelpers(&printer, decl)
+ default:
+ break
+ }
}
}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
index 7bcbd13a5..ffee615f7 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -349,17 +349,15 @@ extension JNISwift2JavaGenerator {
/// Prints helpers for specific types like `Foundation.Date`
private func printSpecificTypeHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- guard let knownType = decl.swiftNominal.knownTypeKind else { return }
-
- switch knownType {
- case .foundationDate, .essentialsDate:
- printFoundationDateHelpers(&printer, decl)
-
- case .foundationData, .essentialsData:
- printFoundationDataHelpers(&printer, decl)
-
- default:
- break
+ if decl.swiftNominal.moduleName == "SwiftJava" {
+ switch decl.swiftNominal.qualifiedName {
+ case "Date":
+ printFoundationDateHelpers(&printer, decl)
+ case "Data":
+ printFoundationDataHelpers(&printer, decl)
+ default:
+ break
+ }
}
}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
index 233a95df9..1883eebd2 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
@@ -286,7 +286,7 @@ extension JNISwift2JavaGenerator {
}
private func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws {
- printHeader(&printer)
+ printHeader(&printer, nil)
for decl in analysis.importedGlobalFuncs {
printSwiftFunctionThunk(&printer, decl)
@@ -300,7 +300,7 @@ extension JNISwift2JavaGenerator {
}
private func printNominalTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) throws {
- printHeader(&printer)
+ printHeader(&printer, type)
printJNICache(&printer, type)
printer.println()
@@ -829,17 +829,20 @@ extension JNISwift2JavaGenerator {
}
}
- private func printHeader(_ printer: inout CodePrinter) {
- printer.print(
- """
- // Generated by swift-java
-
- import SwiftJava
- import SwiftJavaJNICore
- import SwiftJavaRuntimeSupport
-
- """
- )
+ private func printHeader(_ printer: inout CodePrinter, _ type: ImportedNominalType?) {
+ var imports = [
+ "SwiftJava",
+ "SwiftJavaJNICore",
+ ]
+ if type?.swiftNominal.moduleName != "SwiftJavaRuntimeSupport" {
+ imports.append("SwiftJavaRuntimeSupport")
+ }
+ printer.print("// Generated by swift-java")
+ printer.println()
+ for package in imports {
+ printer.print("import \(package)")
+ }
+ printer.println()
self.lookupContext.symbolTable.printImportedModules(&printer)
}
@@ -869,15 +872,14 @@ extension JNISwift2JavaGenerator {
/// Prints thunks for specific known types like Foundation.Date, Foundation.Data
private func printSpecificTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) {
- guard let knownType = type.swiftNominal.knownTypeKind else { return }
-
- switch knownType {
- case .foundationData, .essentialsData:
- printFoundationDataThunks(&printer, type)
- printer.println()
-
- default:
- break
+ if type.swiftNominal.moduleName == "SwiftJava" {
+ switch type.swiftNominal.qualifiedName {
+ case "Data":
+ printFoundationDataThunks(&printer, type)
+ printer.println()
+ default:
+ break
+ }
}
}
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
deleted file mode 100644
index 2451ccd0b..000000000
--- a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
+++ /dev/null
@@ -1,86 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
-
-import SwiftJava
-import SwiftJavaJNICore
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-@JavaImplementation("org.swift.swiftkit.core.foundation.Data")
-extension Data {
- @JavaMethod("$init")
- static func _init(environment: UnsafeMutablePointer!, bytes: [UInt8]) -> Int64 {
- let result$ = UnsafeMutablePointer.allocate(capacity: 1)
- result$.initialize(to: Data(bytes))
- return Int64(Int(bitPattern: result$))
- }
-
- @JavaMethod("$getCount")
- static func _getCount(environment: UnsafeMutablePointer!, selfPointer: Int64) -> Int64 {
- let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
- guard let selfPointer$ else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return Int64(selfPointer$.pointee.count)
- }
-
- @JavaMethod("$typeMetadataAddressDowncall")
- static func _typeMetadataAddressDowncall(environment: UnsafeMutablePointer!) -> Int64 {
- let metadataPointer = unsafeBitCast(Data.self, to: UnsafeRawPointer.self)
- return Int64(Int(bitPattern: metadataPointer))
- }
-}
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J")
-public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jbyteArray? {
- guard let env$ = environment else {
- fatalError("Missing JNIEnv in downcall to \(#function)")
- }
- assert(selfPointer != 0, "selfPointer memory address was null")
- let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: env$))
- guard let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$) else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return selfPointer$.pointee.withUnsafeBytes { buffer in
- buffer.getJNIValue(in: environment)
- }
-}
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J")
-public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J(
- environment: UnsafeMutablePointer!,
- thisClass: jclass,
- selfPointer: jlong
-) -> jbyteArray? {
- guard let env$ = environment else {
- fatalError("Missing JNIEnv in downcall to \(#function)")
- }
- assert(selfPointer != 0, "selfPointer memory address was null")
- let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: env$))
- guard let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$) else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- // This is a double copy, we need to initialize the array and then copy into a JVM array in getJNIValue
- return [UInt8](selfPointer$.pointee).getJNIValue(in: environment)
-}
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift
new file mode 100644
index 000000000..1637eb1fc
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift
@@ -0,0 +1,91 @@
+// ==== --------------------------------------------------
+// Thunks for Data
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_Data {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:177
+
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024init___3B")
+public func Java_org_swift_swiftkit_core_foundation_Data__00024init___3B(environment: UnsafeMutablePointer!, thisClass: jclass, bytes: jbyteArray?) -> jlong {
+ let result$ = UnsafeMutablePointer.allocate(capacity: 1)
+ result$.initialize(to: Data.init([UInt8](fromJNI: bytes, in: environment)))
+ let resultBits$ = Int64(Int(bitPattern: result$))
+ return resultBits$.getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:819
+
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024getCount__J")
+public func Java_org_swift_swiftkit_core_foundation_Data__00024getCount__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong {
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: environment))
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$)
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return Int64(selfPointer$.pointee.count).getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:819
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J")
+public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jbyteArray? {
+ guard let env$ = environment else {
+ fatalError("Missing JNIEnv in downcall to \(#function)")
+ }
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: env$))
+ guard let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$) else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return selfPointer$.pointee.withUnsafeBytes { buffer in
+ buffer.getJNIValue(in: environment)
+ }
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:819
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J")
+public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J(
+ environment: UnsafeMutablePointer!,
+ thisClass: jclass,
+ selfPointer: jlong
+) -> jbyteArray? {
+ guard let env$ = environment else {
+ fatalError("Missing JNIEnv in downcall to \(#function)")
+ }
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: env$))
+ guard let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$) else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ // This is a double copy, we need to initialize the array and then copy into a JVM array in getJNIValue
+ return [UInt8](selfPointer$.pointee).getJNIValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:819
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024typeMetadataAddressDowncall__")
+public func Java_org_swift_swiftkit_core_foundation_Data__00024typeMetadataAddressDowncall__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
+ let metadataPointer = unsafeBitCast(Data.self, to: UnsafeRawPointer.self)
+ return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:819
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift
new file mode 100644
index 000000000..eb9dd1dad
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift
@@ -0,0 +1,17 @@
+// ==== --------------------------------------------------
+// Thunks for DataProtocol
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_DataProtocol {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:177
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift
deleted file mode 100644
index 3c27cd7af..000000000
--- a/Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift
+++ /dev/null
@@ -1,47 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
-
-import SwiftJava
-import SwiftJavaJNICore
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-@JavaImplementation("org.swift.swiftkit.core.foundation.Date")
-extension Date {
- @JavaMethod("$init")
- static func _init(environment: UnsafeMutablePointer!, timeIntervalSince1970: Double) -> Int64 {
- let result$ = UnsafeMutablePointer.allocate(capacity: 1)
- result$.initialize(to: Date(timeIntervalSince1970: timeIntervalSince1970))
- return Int64(Int(bitPattern: result$))
- }
-
- @JavaMethod("$getTimeIntervalSince1970")
- static func _getTimeIntervalSince1970(environment: UnsafeMutablePointer!, selfPointer: Int64) -> Double {
- let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
- guard let selfPointer$ else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return selfPointer$.pointee.timeIntervalSince1970
- }
-
- @JavaMethod("$typeMetadataAddressDowncall")
- static func _typeMetadataAddressDowncall(environment: UnsafeMutablePointer!) -> Int64 {
- let metadataPointer = unsafeBitCast(Date.self, to: UnsafeRawPointer.self)
- return Int64(Int(bitPattern: metadataPointer))
- }
-}
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift
new file mode 100644
index 000000000..920167cbb
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift
@@ -0,0 +1,55 @@
+// ==== --------------------------------------------------
+// Thunks for Date
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_Date {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:177
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Date__00024init__D")
+public func Java_org_swift_swiftkit_core_foundation_Date__00024init__D(environment: UnsafeMutablePointer!, thisClass: jclass, timeIntervalSince1970: jdouble) -> jlong {
+ let result$ = UnsafeMutablePointer.allocate(capacity: 1)
+ result$.initialize(to: Date.init(timeIntervalSince1970: Double(fromJNI: timeIntervalSince1970, in: environment)))
+ let resultBits$ = Int64(Int(bitPattern: result$))
+ return resultBits$.getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:819
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Date__00024getTimeIntervalSince1970__J")
+public func Java_org_swift_swiftkit_core_foundation_Date__00024getTimeIntervalSince1970__J(
+ environment: UnsafeMutablePointer!,
+ thisClass: jclass,
+ selfPointer: jlong
+) -> jdouble {
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: environment))
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$)
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return selfPointer$.pointee.timeIntervalSince1970.getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:819
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Date__00024typeMetadataAddressDowncall__")
+public func Java_org_swift_swiftkit_core_foundation_Date__00024typeMetadataAddressDowncall__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
+ let metadataPointer = unsafeBitCast(Date.self, to: UnsafeRawPointer.self)
+ return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:819
diff --git a/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift b/Sources/SwiftRuntimeFunctions/foundation/Data+SwiftJava.swift
similarity index 70%
rename from Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
rename to Sources/SwiftRuntimeFunctions/foundation/Data+SwiftJava.swift
index b7e2b6ab5..2f9970b8a 100644
--- a/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
+++ b/Sources/SwiftRuntimeFunctions/foundation/Data+SwiftJava.swift
@@ -1,16 +1,5 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
+// Generated by swift-java
+
#if canImport(FoundationEssentials)
import FoundationEssentials
@@ -60,11 +49,3 @@ public func swiftjava_SwiftRuntimeFunctions_Data_copyBytes__(
destinationPointer.copyMemory(from: buffer.baseAddress!, byteCount: count)
}
}
-
-// ==== --------------------------------------------------
-// Thunks for DataProtocol
-
-@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_DataProtocol")
-public func swiftjava_getType_SwiftRuntimeFunctions_DataProtocol() -> UnsafeMutableRawPointer /* Any.Type */ {
- unsafeBitCast((any DataProtocol).self, to: UnsafeMutableRawPointer.self)
-}
diff --git a/Sources/SwiftRuntimeFunctions/foundation/DataProtocol+SwiftJava.swift b/Sources/SwiftRuntimeFunctions/foundation/DataProtocol+SwiftJava.swift
new file mode 100644
index 000000000..30db7ec84
--- /dev/null
+++ b/Sources/SwiftRuntimeFunctions/foundation/DataProtocol+SwiftJava.swift
@@ -0,0 +1,17 @@
+// Generated by swift-java
+
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+
+// ==== --------------------------------------------------
+// Thunks for DataProtocol
+
+@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_DataProtocol")
+public func swiftjava_getType_SwiftRuntimeFunctions_DataProtocol() -> UnsafeMutableRawPointer /* Any.Type */ {
+ unsafeBitCast(DataProtocol.self, to: UnsafeMutableRawPointer.self)
+}
diff --git a/Sources/SwiftRuntimeFunctions/generated/SwiftJavaError+SwiftJava.swift b/Sources/SwiftRuntimeFunctions/generated/SwiftJavaError+SwiftJava.swift
index bdc2d8494..3faaa80b5 100644
--- a/Sources/SwiftRuntimeFunctions/generated/SwiftJavaError+SwiftJava.swift
+++ b/Sources/SwiftRuntimeFunctions/generated/SwiftJavaError+SwiftJava.swift
@@ -1,6 +1,5 @@
// Generated by swift-java
-import SwiftRuntimeFunctions
// ==== --------------------------------------------------
// Thunks for SwiftJavaError
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
index b4f58e69c..bd9afe7cb 100644
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
@@ -1,32 +1,23 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
+// Generated by jextract-swift
+// Swift module: SwiftJava
package org.swift.swiftkit.core.foundation;
import org.swift.swiftkit.core.*;
import org.swift.swiftkit.core.util.*;
import org.swift.swiftkit.core.collections.*;
-
-import java.util.Objects;
+import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import org.swift.swiftkit.core.annotations.*;
public final class Data implements JNISwiftInstance, DataProtocol {
+ static final String LIB_NAME = "SwiftJava";
+
@SuppressWarnings("unused")
private static final boolean INITIALIZED_LIBS = initializeLibs();
static boolean initializeLibs() {
System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ System.loadLibrary(LIB_NAME);
return true;
}
/**
@@ -38,11 +29,11 @@ static boolean initializeLibs() {
private Data(long selfPointer, SwiftArena swiftArena) {
SwiftObjects.requireNonZero(selfPointer, "selfPointer");
this.selfPointer = selfPointer;
-
+
// Only register once we have fully initialized the object since this will need the object pointer.
swiftArena.register(this);
- }
-
+ } // printConcreteType(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:241
+
/**
* Assume that the passed {@code long} represents a memory address of a {@link Data}.
*
@@ -55,30 +46,30 @@ private Data(long selfPointer, SwiftArena swiftArena) {
public static Data wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
return new Data(selfPointer, swiftArena);
}
-
+
public static Data wrapMemoryAddressUnsafe(long selfPointer) {
return new Data(selfPointer, SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA);
}
/** Pointer to the "self". */
private final long selfPointer;
-
+
/** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */
private final AtomicBoolean $state$destroyed = new AtomicBoolean(false);
-
+
public long $memoryAddress() {
return this.selfPointer;
}
-
+
@Override
public AtomicBoolean $statusDestroyedFlag() {
return $state$destroyed;
}
-
-
-
+
+
+
// ==== --------------------------------------------------
// Data.init
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -87,14 +78,14 @@ public static Data wrapMemoryAddressUnsafe(long selfPointer) {
*/
public static Data init(@Unsigned byte[] bytes, SwiftArena swiftArena) {
return Data.wrapMemoryAddressUnsafe(Data.$init(Objects.requireNonNull(bytes, "bytes must not be null")), swiftArena);
- }
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:693
private static native long $init(byte[] bytes);
-
-
-
+
+
+
// ==== --------------------------------------------------
// getter:Data.count
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -103,9 +94,9 @@ public static Data init(@Unsigned byte[] bytes, SwiftArena swiftArena) {
*/
public long getCount() {
return Data.$getCount(this.$memoryAddress());
- }
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:693
private static native long $getCount(long selfPointer);
-
+
/**
* Creates a new Swift @{link Data} instance from a byte array.
*
@@ -117,16 +108,15 @@ public static Data fromByteArray(byte[] bytes, SwiftArena swiftArena) {
Objects.requireNonNull(bytes, "bytes cannot be null");
return Data.init(bytes, swiftArena);
}
-
/**
* Copies the contents of this Data to a new byte array.
- *
+ *
* This is a relatively efficient implementation, which avoids native array copies,
- * however it will still perform a copy of the data onto the JVM heap, so use this
+ * however it will still perform a copy of the data onto the JVM heap, so use this
* only when necessary.
- *
+ *
* When utmost performance is necessary, you may want to investigate the FFM mode
- * of jextract which is able to map memory more efficiently.
+ * of jextract which is able to map memory more efficiently.
*
* @return A byte array containing a copy of this Data's bytes
*/
@@ -134,36 +124,36 @@ public byte[] toByteArray() {
return $toByteArray(this.$memoryAddress());
}
private static native byte[] $toByteArray(long selfPointer);
-
+
/**
* Copies the contents of this Data to a new byte array.
- *
+ *
* @deprecated Prefer using the `toByteArray` method as it is more performant.
- * This implementation uses a naive conversion path from native bytes into jbytes
+ * This implementation uses a naive conversion path from native bytes into jbytes
* and then copying them onto the jvm heap.
- *
+ *
* @return A byte array containing a copy of this Data's bytes
*/
@Deprecated(forRemoval = true)
public byte[] toByteArrayIndirectCopy() {
return $toByteArrayIndirectCopy(this.$memoryAddress());
}
+
private static native byte[] $toByteArrayIndirectCopy(long selfPointer);
-
private static native long $typeMetadataAddressDowncall();
@Override
public long $typeMetadataAddress() {
return Data.$typeMetadataAddressDowncall();
- }
-
+ } // printTypeMetadataAddressFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:785
+
public String toString() {
return SwiftObjects.toString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
public String toDebugString() {
return SwiftObjects.toDebugString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
@Override
public Runnable $createDestroyFunction() {
long self$ = this.$memoryAddress();
@@ -182,5 +172,5 @@ public void run() {
SwiftObjects.destroy(self$, selfType$);
}
};
- }
-}
+ } // printDestroyFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:799
+} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:411
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
index f3240bc0d..1a9f82f73 100644
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
@@ -1,20 +1,14 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
+// Generated by jextract-swift
+// Swift module: SwiftJava
package org.swift.swiftkit.core.foundation;
-import org.swift.swiftkit.core.JNISwiftInstance;
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.core.collections.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.swift.swiftkit.core.annotations.*;
public interface DataProtocol extends JNISwiftInstance {
-}
+} // printProtocol(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:165
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
index 157fe4f81..59368c852 100644
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
@@ -1,31 +1,23 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
+// Generated by jextract-swift
+// Swift module: SwiftJava
package org.swift.swiftkit.core.foundation;
import org.swift.swiftkit.core.*;
import org.swift.swiftkit.core.util.*;
import org.swift.swiftkit.core.collections.*;
-import java.util.Objects;
+import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import org.swift.swiftkit.core.annotations.*;
public final class Date implements JNISwiftInstance {
+ static final String LIB_NAME = "SwiftJava";
+
@SuppressWarnings("unused")
private static final boolean INITIALIZED_LIBS = initializeLibs();
static boolean initializeLibs() {
System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ System.loadLibrary(LIB_NAME);
return true;
}
/**
@@ -37,11 +29,11 @@ static boolean initializeLibs() {
private Date(long selfPointer, SwiftArena swiftArena) {
SwiftObjects.requireNonZero(selfPointer, "selfPointer");
this.selfPointer = selfPointer;
-
+
// Only register once we have fully initialized the object since this will need the object pointer.
swiftArena.register(this);
- }
-
+ } // printConcreteType(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:241
+
/**
* Assume that the passed {@code long} represents a memory address of a {@link Date}.
*
@@ -54,29 +46,29 @@ private Date(long selfPointer, SwiftArena swiftArena) {
public static Date wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
return new Date(selfPointer, swiftArena);
}
-
+
public static Date wrapMemoryAddressUnsafe(long selfPointer) {
return new Date(selfPointer, SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA);
}
/** Pointer to the "self". */
private final long selfPointer;
-
+
/** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */
private final AtomicBoolean $state$destroyed = new AtomicBoolean(false);
-
+
public long $memoryAddress() {
return this.selfPointer;
}
-
+
@Override
public AtomicBoolean $statusDestroyedFlag() {
return $state$destroyed;
}
-
-
+
+
// ==== --------------------------------------------------
// Date.init
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -85,13 +77,13 @@ public static Date wrapMemoryAddressUnsafe(long selfPointer) {
*/
public static Date init(double timeIntervalSince1970, SwiftArena swiftArena) {
return Date.wrapMemoryAddressUnsafe(Date.$init(timeIntervalSince1970), swiftArena);
- }
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:693
private static native long $init(double timeIntervalSince1970);
-
-
+
+
// ==== --------------------------------------------------
// getter:Date.timeIntervalSince1970
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -100,9 +92,9 @@ public static Date init(double timeIntervalSince1970, SwiftArena swiftArena) {
*/
public double getTimeIntervalSince1970() {
return Date.$getTimeIntervalSince1970(this.$memoryAddress());
- }
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:693
private static native double $getTimeIntervalSince1970(long selfPointer);
-
+
/**
* Converts this wrapped date to a Java {@link java.time.Instant}.
*
@@ -117,7 +109,7 @@ public java.time.Instant toInstant() {
long nanos = Math.round((this.getTimeIntervalSince1970() - seconds) * 1_000_000_000);
return java.time.Instant.ofEpochSecond(seconds, nanos);
}
-
+
/**
* Initializes a Swift {@code Foundation.Date} from a Java {@link java.time.Instant}.
*
@@ -145,21 +137,20 @@ public static Date fromInstant(java.time.Instant instant, SwiftArena swiftArena)
double timeIntervalSince1970 = instant.getEpochSecond() + (instant.getNano() / 1_000_000_000.0);
return Date.init(timeIntervalSince1970, swiftArena);
}
-
private static native long $typeMetadataAddressDowncall();
@Override
public long $typeMetadataAddress() {
return Date.$typeMetadataAddressDowncall();
- }
-
+ } // printTypeMetadataAddressFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:785
+
public String toString() {
return SwiftObjects.toString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
public String toDebugString() {
return SwiftObjects.toDebugString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
@Override
public Runnable $createDestroyFunction() {
long self$ = this.$memoryAddress();
@@ -178,5 +169,5 @@ public void run() {
SwiftObjects.destroy(self$, selfType$);
}
};
- }
-}
+ } // printDestroyFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:799
+} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:411
diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java
index ffeaea2eb..04a9603e5 100644
--- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java
@@ -1,16 +1,5 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
+// Generated by jextract-swift
+// Swift module: SwiftRuntimeFunctions
package org.swift.swiftkit.ffm.foundation;
@@ -22,6 +11,7 @@
import java.lang.foreign.*;
import java.lang.invoke.*;
import java.util.*;
+import java.nio.charset.StandardCharsets;
public final class Data extends FFMSwiftInstance implements SwiftValue {
static final String LIB_NAME = "SwiftRuntimeFunctions";
@@ -35,22 +25,22 @@ static boolean initializeLibs() {
SwiftLibraries.loadLibraryWithFallbacks(LIB_NAME);
return true;
}
-
+
public static final SwiftAnyType TYPE_METADATA =
new SwiftAnyType(SwiftRuntime.swiftjava.getType("SwiftRuntimeFunctions", "Data"));
- public SwiftAnyType $swiftType() {
+ public final SwiftAnyType $swiftType() {
return TYPE_METADATA;
}
-
+
public static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment());
- public GroupLayout $layout() {
+ public final GroupLayout $layout() {
return $LAYOUT;
}
-
+
private Data(MemorySegment segment, AllocatingSwiftArena arena) {
super(segment, arena);
}
-
+
/**
* Assume that the passed {@code MemorySegment} represents a memory address of a {@link Data}.
*
@@ -63,10 +53,10 @@ private Data(MemorySegment segment, AllocatingSwiftArena arena) {
public static Data wrapMemoryAddressUnsafe(MemorySegment selfPointer, AllocatingSwiftArena arena) {
return new Data(selfPointer, arena);
}
-
+
// ==== --------------------------------------------------
// Data.init
-
+
/**
* {@snippet lang=c :
* void swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count(const void *bytes, ptrdiff_t count, void *_result)
@@ -79,7 +69,7 @@ private static class swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count {
/* _result: */SwiftValueLayout.SWIFT_POINTER
);
private static final MemorySegment ADDR =
- SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count");
+ SwiftRuntimeFunctions.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count");
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
public static void call(java.lang.foreign.MemorySegment bytes, long count, java.lang.foreign.MemorySegment _result) {
try {
@@ -91,8 +81,7 @@ public static void call(java.lang.foreign.MemorySegment bytes, long count, java.
throw new AssertionError("should not reach here", ex$);
}
}
- }
-
+ } // printJavaBindingDescriptorClass(_:_:symbolLookup:additionalContent:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:65
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -104,15 +93,15 @@ public static Data init(java.lang.foreign.MemorySegment bytes, long count, Alloc
if (SwiftValueLayout.has32bitSwiftInt) {
if (count < Integer.MIN_VALUE || count > Integer.MAX_VALUE) {
throw new SwiftIntegerOverflowException("Parameter 'count' overflow: " + count);
- }
- }
+ } // printDowncall(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:506
+ } // printDowncall(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:498
swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count.call(bytes, count, result$);
return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
- }
-
+ } // printJavaBindingWrapperMethod(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:403
+
// ==== --------------------------------------------------
// Data.init
-
+
/**
* {@snippet lang=c :
* void swiftjava_SwiftRuntimeFunctions_Data_init__(const void *bytes_pointer, ptrdiff_t bytes_count, void *_result)
@@ -125,7 +114,7 @@ private static class swiftjava_SwiftRuntimeFunctions_Data_init__ {
/* _result: */SwiftValueLayout.SWIFT_POINTER
);
private static final MemorySegment ADDR =
- SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_init__");
+ SwiftRuntimeFunctions.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_init__");
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
public static void call(java.lang.foreign.MemorySegment bytes_pointer, long bytes_count, java.lang.foreign.MemorySegment _result) {
try {
@@ -137,8 +126,7 @@ public static void call(java.lang.foreign.MemorySegment bytes_pointer, long byte
throw new AssertionError("should not reach here", ex$);
}
}
- }
-
+ } // printJavaBindingDescriptorClass(_:_:symbolLookup:additionalContent:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:65
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -151,11 +139,11 @@ public static Data init(@Unsigned byte[] bytes, AllocatingSwiftArena swiftArena)
swiftjava_SwiftRuntimeFunctions_Data_init__.call(arena$.allocateFrom(ValueLayout.JAVA_BYTE, bytes), bytes.length, result$);
return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
}
- }
-
+ } // printJavaBindingWrapperMethod(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:403
+
// ==== --------------------------------------------------
// getter:Data.count
-
+
/**
* {@snippet lang=c :
* ptrdiff_t swiftjava_SwiftRuntimeFunctions_Data_count$get(const void *self)
@@ -167,7 +155,7 @@ private static class swiftjava_SwiftRuntimeFunctions_Data_count$get {
/* self: */SwiftValueLayout.SWIFT_POINTER
);
private static final MemorySegment ADDR =
- SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_count$get");
+ SwiftRuntimeFunctions.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_count$get");
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
public static long call(java.lang.foreign.MemorySegment self) {
try {
@@ -179,8 +167,7 @@ public static long call(java.lang.foreign.MemorySegment self) {
throw new AssertionError("should not reach here", ex$);
}
}
- }
-
+ } // printJavaBindingDescriptorClass(_:_:symbolLookup:additionalContent:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:65
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -193,14 +180,14 @@ public long getCount() throws SwiftIntegerOverflowException {
if (SwiftValueLayout.has32bitSwiftInt) {
if (result$checked < Integer.MIN_VALUE || result$checked > Integer.MAX_VALUE) {
throw new SwiftIntegerOverflowException("Return value overflow: " + result$checked);
- }
- }
+ } // printReturnWithOverflowCheck(_:value:overflowCheck:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:603
+ } // printReturnWithOverflowCheck(_:value:overflowCheck:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:602
return result$checked;
- }
-
+ } // printJavaBindingWrapperMethod(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:403
+
// ==== --------------------------------------------------
// Data.withUnsafeBytes
-
+
/**
* {@snippet lang=c :
* void swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__(void (*body)(const void *, ptrdiff_t), const void *self)
@@ -212,7 +199,7 @@ private static class swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__ {
/* self: */SwiftValueLayout.SWIFT_POINTER
);
private static final MemorySegment ADDR =
- SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__");
+ SwiftRuntimeFunctions.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__");
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
public static void call(java.lang.foreign.MemorySegment body, java.lang.foreign.MemorySegment self) {
try {
@@ -242,8 +229,8 @@ public interface Function {
private static MemorySegment toUpcallStub(Function fi, Arena arena) {
return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena);
}
- }
- }
+ } // printFunctionPointerParameterDescriptorClass(_:_:_:impl:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:223
+ } // printJavaBindingDescriptorClass(_:_:symbolLookup:additionalContent:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:65
public static class withUnsafeBytes {
@FunctionalInterface
public interface body {
@@ -253,9 +240,8 @@ public interface body {
return swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__.$body.toUpcallStub((_0_pointer, _0_count) -> {
fi.apply(_0_pointer.reinterpret(_0_count));
}, arena);
- }
- }
-
+ } // printJavaBindingWrapperFunctionTypeHelper(_:_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:327
+ } // printJavaBindingWrapperHelperClass(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:280
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -267,11 +253,11 @@ public void withUnsafeBytes(withUnsafeBytes.body body) {
try(var arena$ = Arena.ofConfined()) {
swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__.call(withUnsafeBytes.$toUpcallStub(body, arena$), this.$memorySegment());
}
- }
-
+ } // printJavaBindingWrapperMethod(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:403
+
// ==== --------------------------------------------------
// Data helper methods
-
+
/**
* Creates a new Swift {@link Data} instance from a byte array.
*
@@ -283,7 +269,6 @@ public static Data fromByteArray(byte[] bytes, AllocatingSwiftArena arena) {
Objects.requireNonNull(bytes, "bytes cannot be null");
return Data.init(bytes, arena);
}
-
/**
* {@snippet lang=c :
* void swiftjava_SwiftRuntimeFunctions_Data_copyBytes__(void *const self, void *destination, ptrdiff_t count)
@@ -296,7 +281,7 @@ private static class swiftjava_SwiftRuntimeFunctions_Data_copyBytes__ {
/* count: */SwiftValueLayout.SWIFT_INT
);
private static final MemorySegment ADDR =
- SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_copyBytes__");
+ SwiftRuntimeFunctions.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_copyBytes__");
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
public static void call(java.lang.foreign.MemorySegment self, java.lang.foreign.MemorySegment destination, long count) {
try {
@@ -308,8 +293,7 @@ public static void call(java.lang.foreign.MemorySegment self, java.lang.foreign.
throw new AssertionError("should not reach here", ex$);
}
}
- }
-
+ } // printJavaBindingDescriptorClass(_:_:symbolLookup:additionalContent:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:65
/**
* Copies the contents of this Data to a new {@link MemorySegment}.
*
@@ -329,9 +313,8 @@ public MemorySegment toMemorySegment(AllocatingSwiftArena arena) {
swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
return segment;
}
-
/**
- * Copies the contents of this Data to a new {@link java.nio.ByteBuffer}.
+ * Copies the contents of this Data to a new {@link ByteBuffer}.
*
* The returned {@link java.nio.ByteBuffer} is a view over native memory and is valid for the
* lifetime of the arena. This avoids an additional copy to the Java heap.
@@ -349,7 +332,6 @@ public java.nio.ByteBuffer toByteBuffer(AllocatingSwiftArena arena) {
swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
return segment.asByteBuffer();
}
-
/**
* Copies the contents of this Data to a new byte array.
* The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
@@ -370,7 +352,6 @@ public byte[] toByteArray(AllocatingSwiftArena arena) {
swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
return segment.toArray(ValueLayout.JAVA_BYTE);
}
-
/**
* Copies the contents of this Data to a new byte array.
* The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
@@ -403,4 +384,4 @@ public String toString() {
+ ")@"
+ $memorySegment();
}
-}
+} // printNominal(_:_:body:) @ JExtractSwiftLib/FFMSwift2JavaGenerator.swift:395
diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java
index 2881ac85e..8d16ef379 100644
--- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java
@@ -1,16 +1,5 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
+// Generated by jextract-swift
+// Swift module: SwiftRuntimeFunctions
package org.swift.swiftkit.ffm.foundation;
@@ -22,6 +11,7 @@
import java.lang.foreign.*;
import java.lang.invoke.*;
import java.util.*;
+import java.nio.charset.StandardCharsets;
public final class DataProtocol extends FFMSwiftInstance implements SwiftValue {
static final String LIB_NAME = "SwiftRuntimeFunctions";
@@ -35,22 +25,22 @@ static boolean initializeLibs() {
SwiftLibraries.loadLibraryWithFallbacks(LIB_NAME);
return true;
}
-
+
public static final SwiftAnyType TYPE_METADATA =
new SwiftAnyType(SwiftRuntime.swiftjava.getType("SwiftRuntimeFunctions", "DataProtocol"));
- public SwiftAnyType $swiftType() {
+ public final SwiftAnyType $swiftType() {
return TYPE_METADATA;
}
-
+
public static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment());
- public GroupLayout $layout() {
+ public final GroupLayout $layout() {
return $LAYOUT;
}
-
+
private DataProtocol(MemorySegment segment, AllocatingSwiftArena arena) {
super(segment, arena);
}
-
+
/**
* Assume that the passed {@code MemorySegment} represents a memory address of a {@link DataProtocol}.
*
@@ -63,7 +53,6 @@ private DataProtocol(MemorySegment segment, AllocatingSwiftArena arena) {
public static DataProtocol wrapMemoryAddressUnsafe(MemorySegment selfPointer, AllocatingSwiftArena arena) {
return new DataProtocol(selfPointer, arena);
}
-
@Override
public String toString() {
return getClass().getSimpleName()
@@ -72,4 +61,4 @@ public String toString() {
+ ")@"
+ $memorySegment();
}
-}
+} // printNominal(_:_:body:) @ JExtractSwiftLib/FFMSwift2JavaGenerator.swift:395
diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftJavaErrorException.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftJavaErrorException.java
index ce276caa7..aff2eccee 100644
--- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftJavaErrorException.java
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftJavaErrorException.java
@@ -127,4 +127,4 @@ private static String fetchDescription(MemorySegment errorPointer) {
return "Swift error (address: 0x" + Long.toHexString(errorPointer.address()) + ")";
}
}
-} // printNominal(_:_:body:) @ JExtractSwiftLib/FFMSwift2JavaGenerator.swift:385
+} // printNominal(_:_:body:) @ JExtractSwiftLib/FFMSwift2JavaGenerator.swift:395
diff --git a/scripts/swiftkit-ffm-generate-bindings.sh b/scripts/swiftkit-ffm-generate-bindings.sh
index 9f706a77c..43cb277e9 100755
--- a/scripts/swiftkit-ffm-generate-bindings.sh
+++ b/scripts/swiftkit-ffm-generate-bindings.sh
@@ -23,15 +23,18 @@ set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
JAVA_OUTPUT="${REPO_ROOT}/SwiftKitFFM/src/main/java"
-JAVA_PACKAGE="org.swift.swiftkit.ffm.generated"
+PACKAGE_GENERATED="org.swift.swiftkit.ffm.generated"
+PACKAGE_FOUNDATION="org.swift.swiftkit.ffm.foundation"
-# Declare types to generate: SWIFT_MODULE SINGLE_TYPE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
+# Declare types to generate: SWIFT_MODULE SINGLE_TYPE JAVA_PACKAGE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
TYPES=(
- "SwiftRuntimeFunctions SwiftJavaError Sources/SwiftRuntimeFunctions Sources/SwiftRuntimeFunctions/generated"
+ "SwiftRuntimeFunctions SwiftJavaError ${PACKAGE_GENERATED} Sources/SwiftRuntimeFunctions Sources/SwiftRuntimeFunctions/generated"
+ "SwiftRuntimeFunctions Data ${PACKAGE_FOUNDATION} Sources/FakeFoundation Sources/SwiftRuntimeFunctions/foundation"
+ "SwiftRuntimeFunctions DataProtocol ${PACKAGE_FOUNDATION} Sources/FakeFoundation Sources/SwiftRuntimeFunctions/foundation"
)
for entry in "${TYPES[@]}"; do
- read -r MODULE SINGLE_TYPE INPUT_SWIFT OUTPUT_SWIFT <<< "$entry"
+ read -r MODULE SINGLE_TYPE JAVA_PACKAGE INPUT_SWIFT OUTPUT_SWIFT <<< "$entry"
echo "==> Generating ${SINGLE_TYPE} (module: ${MODULE})..."
diff --git a/scripts/swiftkit-jni-generate-bindings.sh b/scripts/swiftkit-jni-generate-bindings.sh
index 7af973949..285350b64 100755
--- a/scripts/swiftkit-jni-generate-bindings.sh
+++ b/scripts/swiftkit-jni-generate-bindings.sh
@@ -27,8 +27,9 @@ JAVA_PACKAGE="org.swift.swiftkit.core.foundation"
# Declare types to generate: SWIFT_MODULE SINGLE_TYPE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
TYPES=(
- "Foundation Data Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/foundation"
- "Foundation Date Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/foundation"
+ "SwiftJava Data Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/foundation"
+ "SwiftJava DataProtocol Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/foundation"
+ "SwiftJava Date Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/foundation"
)
for entry in "${TYPES[@]}"; do
From baecaf202f453c66215bda0730665280db65b796 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 15:47:38 +0900
Subject: [PATCH 15/17] add public accessor
---
Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift | 2 +-
.../swift/swiftkit/ffm/generated/SwiftRuntimeFunctions.java | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
index 8427208c3..65a3d9d65 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
@@ -448,7 +448,7 @@ extension FFMSwift2JavaGenerator {
printer.print(
"""
- static MemorySegment findOrThrow(String symbol) {
+ public static MemorySegment findOrThrow(String symbol) {
return SYMBOL_LOOKUP.find(symbol)
.orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol)));
}
diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftRuntimeFunctions.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftRuntimeFunctions.java
index ec27f2a29..ff7765dfb 100644
--- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftRuntimeFunctions.java
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftRuntimeFunctions.java
@@ -17,14 +17,14 @@ public final class SwiftRuntimeFunctions {
private SwiftRuntimeFunctions() {
// Should not be called directly
}
-
+
// Static enum to force initialization
private static enum Initializer {
FORCE; // Refer to this to force outer Class initialization (and static{} blocks to trigger)
}
static final String LIB_NAME = "SwiftRuntimeFunctions";
static final Arena LIBRARY_ARENA = Arena.ofAuto();
- static MemorySegment findOrThrow(String symbol) {
+ public static MemorySegment findOrThrow(String symbol) {
return SYMBOL_LOOKUP.find(symbol)
.orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol)));
}
@@ -49,7 +49,7 @@ private static SymbolLookup getSymbolLookup() {
SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_RUNTIME_FUNCTIONS);
SwiftLibraries.loadLibraryWithFallbacks(LIB_NAME);
}
-
+
if (PlatformUtils.isMacOS()) {
return SymbolLookup.libraryLookup(System.mapLibraryName(LIB_NAME), LIBRARY_ARENA)
.or(SymbolLookup.loaderLookup())
From ee1ce478685922d02508aefe56c396e97d291ef3 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 16:37:03 +0900
Subject: [PATCH 16/17] fix stripping import target module name
---
.../JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift | 2 +-
Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift | 1 -
.../Foundation/DataProtocol+SwiftJava.swift | 1 -
Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift | 1 -
4 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
index 1883eebd2..fdf1db9f3 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
@@ -834,7 +834,7 @@ extension JNISwift2JavaGenerator {
"SwiftJava",
"SwiftJavaJNICore",
]
- if type?.swiftNominal.moduleName != "SwiftJavaRuntimeSupport" {
+ if !(type?.swiftNominal.moduleName == "SwiftJava") {
imports.append("SwiftJavaRuntimeSupport")
}
printer.print("// Generated by swift-java")
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift
index 1637eb1fc..3e8c20d68 100644
--- a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift
@@ -5,7 +5,6 @@
import SwiftJava
import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
#if canImport(FoundationEssentials)
import FoundationEssentials
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift
index eb9dd1dad..ad62ac0a0 100644
--- a/Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift
@@ -5,7 +5,6 @@
import SwiftJava
import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
#if canImport(FoundationEssentials)
import FoundationEssentials
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift
index 920167cbb..6a240919a 100644
--- a/Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift
@@ -5,7 +5,6 @@
import SwiftJava
import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
#if canImport(FoundationEssentials)
import FoundationEssentials
From ac26e217fed14e3874ff8189ed0e43774c8f9c64 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 17:22:50 +0900
Subject: [PATCH 17/17] Update .licenseignore
---
.licenseignore | 4 ++++
.../{foundation => Foundation}/Data+SwiftJava.swift | 0
.../{foundation => Foundation}/DataProtocol+SwiftJava.swift | 0
3 files changed, 4 insertions(+)
rename Sources/SwiftRuntimeFunctions/{foundation => Foundation}/Data+SwiftJava.swift (100%)
rename Sources/SwiftRuntimeFunctions/{foundation => Foundation}/DataProtocol+SwiftJava.swift (100%)
diff --git a/.licenseignore b/.licenseignore
index a49ab625d..b8009e6df 100644
--- a/.licenseignore
+++ b/.licenseignore
@@ -52,3 +52,7 @@ Samples/JavaDependencySampleApp/gradle
Sources/_Subprocess/**
Sources/_SubprocessCShims/**
Samples/gradle
+Sources/SwiftJavaRuntimeSupport/Foundation/*
+Sources/SwiftRuntimeFunctions/Foundation/*
+SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/*
+SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/*
diff --git a/Sources/SwiftRuntimeFunctions/foundation/Data+SwiftJava.swift b/Sources/SwiftRuntimeFunctions/Foundation/Data+SwiftJava.swift
similarity index 100%
rename from Sources/SwiftRuntimeFunctions/foundation/Data+SwiftJava.swift
rename to Sources/SwiftRuntimeFunctions/Foundation/Data+SwiftJava.swift
diff --git a/Sources/SwiftRuntimeFunctions/foundation/DataProtocol+SwiftJava.swift b/Sources/SwiftRuntimeFunctions/Foundation/DataProtocol+SwiftJava.swift
similarity index 100%
rename from Sources/SwiftRuntimeFunctions/foundation/DataProtocol+SwiftJava.swift
rename to Sources/SwiftRuntimeFunctions/Foundation/DataProtocol+SwiftJava.swift