diff --git a/Sources/JExtractSwiftLib/FFM/ConversionStep.swift b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift
index 656d9dd9..f59f739d 100644
--- a/Sources/JExtractSwiftLib/FFM/ConversionStep.swift
+++ b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift
@@ -123,7 +123,7 @@ enum ConversionStep: Equatable {
// of splatting out text.
let renderedArgumentList = renderedArguments.joined(separator: ", ")
return "\(raw: type.description)(\(raw: renderedArgumentList))"
-
+
case .tuplify(let elements):
let renderedElements: [String] = elements.enumerated().map { (index, element) in
element.asExprSyntax(placeholder: "\(placeholder)_\(index)", bodyItems: &bodyItems)!.description
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
index b8749299..84a90275 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -407,6 +407,7 @@ extension FFMSwift2JavaGenerator {
"arena$"
}
+ // FIXME: use trailing$ convention
let varName = outParameter.name.isEmpty ? "_result" : "_result_" + outParameter.name
printer.print(
@@ -463,7 +464,7 @@ extension FFMSwift2JavaGenerator.JavaConversionStep {
switch self {
case .placeholder, .explodedName, .constant, .readMemorySegment:
return false
- case .constructSwiftValue:
+ case .constructSwiftValue, .wrapMemoryAddressUnsafe:
return true
case .call(let inner, _, _), .cast(let inner, _), .construct(let inner, _),
@@ -482,7 +483,11 @@ extension FFMSwift2JavaGenerator.JavaConversionStep {
return false
case .readMemorySegment:
return true
- case .cast(let inner, _), .construct(let inner, _), .constructSwiftValue(let inner, _), .swiftValueSelfSegment(let inner):
+ case .cast(let inner, _),
+ .construct(let inner, _),
+ .constructSwiftValue(let inner, _),
+ .swiftValueSelfSegment(let inner),
+ .wrapMemoryAddressUnsafe(let inner, _):
return inner.requiresSwiftArena
case .call(let inner, _, let withArena):
return withArena || inner.requiresTemporaryArena
@@ -522,6 +527,10 @@ extension FFMSwift2JavaGenerator.JavaConversionStep {
let inner = inner.render(&printer, placeholder)
return "new \(javaType.className!)(\(inner), swiftArena$)"
+ case .wrapMemoryAddressUnsafe(let inner, let javaType):
+ let inner = inner.render(&printer, placeholder)
+ return "\(javaType.className!).wrapMemoryAddressUnsafe(\(inner), swiftArena$)"
+
case .construct(let inner, let javaType):
let inner = inner.render(&printer, placeholder)
return "new \(javaType)(\(inner))"
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
index f8b2e7e8..06a4d171 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
@@ -684,7 +684,7 @@ extension FFMSwift2JavaGenerator {
outParameters: [
JavaParameter(name: "", type: javaType)
],
- conversion: .constructSwiftValue(.placeholder, javaType)
+ conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType)
)
case .tuple:
@@ -732,6 +732,9 @@ extension FFMSwift2JavaGenerator {
// Call 'new \(Type)(\(placeholder), swiftArena$)'.
indirect case constructSwiftValue(JavaConversionStep, JavaType)
+ /// Call the `MyType.wrapMemoryAddressUnsafe` in order to wrap a memory address using the Java binding type
+ indirect case wrapMemoryAddressUnsafe(JavaConversionStep, JavaType)
+
// Construct the type using the placeholder as arguments.
indirect case construct(JavaConversionStep, JavaType)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
index 3e60db14..c66b0029 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
@@ -216,9 +216,22 @@ extension FFMSwift2JavaGenerator {
printer.print(
"""
- public \(decl.swiftNominal.name)(MemorySegment segment, AllocatingSwiftArena arena) {
+ private \(decl.swiftNominal.name)(MemorySegment segment, AllocatingSwiftArena arena) {
super(segment, arena);
}
+
+ /**
+ * Assume that the passed {@code MemorySegment} represents a memory address of a {@link \(decl.swiftNominal.name)}.
+ *
+ * Warnings:
+ *
+ * - No checks are performed about the compatibility of the pointed at memory and the actual \(decl.swiftNominal.name) 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 \(decl.swiftNominal.name) wrapMemoryAddressUnsafe(MemorySegment selfPointer, AllocatingSwiftArena swiftArena) {
+ return new \(decl.swiftNominal.name)(selfPointer, swiftArena);
+ }
"""
)
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
index 0920a89b..d3452cef 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -117,9 +117,22 @@ extension JNISwift2JavaGenerator {
printer.print(
"""
- public \(decl.swiftNominal.name)(long selfPointer, SwiftArena swiftArena) {
+ private \(decl.swiftNominal.name)(long selfPointer, SwiftArena swiftArena) {
super(selfPointer, swiftArena);
}
+
+ /**
+ * Assume that the passed {@code long} represents a memory address of a {@link \(decl.swiftNominal.name)}.
+ *
+ * Warnings:
+ *
+ * - No checks are performed about the compatibility of the pointed at memory and the actual \(decl.swiftNominal.name) 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 \(decl.swiftNominal.name) wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
+ return new \(decl.swiftNominal.name)(selfPointer, swiftArena);
+ }
"""
)
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
index 0db77ece..64ae23b7 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
@@ -383,7 +383,7 @@ extension JNISwift2JavaGenerator {
javaType: javaType,
annotations: resultAnnotations,
outParameters: [],
- conversion: .constructSwiftValue(.placeholder, javaType)
+ conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType)
)
case .tuple([]):
@@ -465,7 +465,7 @@ extension JNISwift2JavaGenerator {
discriminatorName: "result_discriminator$",
optionalClass: "Optional",
javaType: .long,
- toValue: .constructSwiftValue(.placeholder, .class(package: nil, name: nominalTypeName))
+ toValue: .wrapMemoryAddressUnsafe(.placeholder, .class(package: nil, name: nominalTypeName))
)
)
@@ -582,6 +582,9 @@ extension JNISwift2JavaGenerator {
/// Call `new \(Type)(\(placeholder), swiftArena$)`
indirect case constructSwiftValue(JavaNativeConversionStep, JavaType)
+ /// Call the `MyType.wrapMemoryAddressUnsafe` in order to wrap a memory address using the Java binding type
+ indirect case wrapMemoryAddressUnsafe(JavaNativeConversionStep, JavaType)
+
indirect case call(JavaNativeConversionStep, function: String)
indirect case method(JavaNativeConversionStep, function: String, arguments: [JavaNativeConversionStep] = [])
@@ -641,6 +644,10 @@ extension JNISwift2JavaGenerator {
case .constructSwiftValue(let inner, let javaType):
let inner = inner.render(&printer, placeholder)
return "new \(javaType.className!)(\(inner), swiftArena$)"
+
+ case .wrapMemoryAddressUnsafe(let inner, let javaType):
+ let inner = inner.render(&printer, placeholder)
+ return "\(javaType.className!).wrapMemoryAddressUnsafe(\(inner), swiftArena$)"
case .call(let inner, let function):
let inner = inner.render(&printer, placeholder)
@@ -705,7 +712,7 @@ extension JNISwift2JavaGenerator {
case .placeholder, .constant, .isOptionalPresent:
return false
- case .constructSwiftValue:
+ case .constructSwiftValue, .wrapMemoryAddressUnsafe:
return true
case .valueMemoryAddress(let inner):
diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift
index 7416779d..cf4ed387 100644
--- a/Tests/JExtractSwiftTests/DataImportTests.swift
+++ b/Tests/JExtractSwiftTests/DataImportTests.swift
@@ -86,7 +86,7 @@ final class DataImportTests {
]
)
}
-
+
@Test("Import Data: JavaBindings")
func data_javaBindings() throws {
@@ -167,7 +167,7 @@ final class DataImportTests {
public static Data returnData(AllocatingSwiftArena swiftArena$) {
MemorySegment _result = swiftArena$.allocate(Data.$LAYOUT);
swiftjava_SwiftModule_returnData.call(_result);
- return new Data(_result, swiftArena$);
+ return Data.wrapMemoryAddressUnsafe(_result, swiftArena$);
}
""",
@@ -210,7 +210,7 @@ final class DataImportTests {
public static Data init(java.lang.foreign.MemorySegment bytes, long count, AllocatingSwiftArena swiftArena$) {
MemorySegment _result = swiftArena$.allocate(Data.$LAYOUT);
swiftjava_SwiftModule_Data_init_bytes_count.call(bytes, count, _result);
- return new Data(_result, swiftArena$);
+ return Data.wrapMemoryAddressUnsafe(_result, swiftArena$);
}
""",
@@ -408,4 +408,5 @@ final class DataImportTests {
]
)
}
+
}
diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift
index 5b015f89..1e33efcb 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift
@@ -66,11 +66,17 @@ struct JNIClassTests {
System.loadLibrary(LIB_NAME);
return true;
}
-
- public MyClass(long selfPointer, SwiftArena swiftArena) {
+ """,
+ """
+ private MyClass(long selfPointer, SwiftArena swiftArena) {
super(selfPointer, swiftArena);
}
""",
+ """
+ public static MyClass wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
+ return new MyClass(selfPointer, swiftArena);
+ }
+ """
])
try assertOutput(
input: source,
@@ -164,7 +170,7 @@ struct JNIClassTests {
* }
*/
public static MyClass init(long x, long y, SwiftArena swiftArena$) {
- return new MyClass(MyClass.$init(x, y), swiftArena$);
+ return MyClass.wrapMemoryAddressUnsafe(MyClass.$init(x, y), swiftArena$);
}
""",
"""
@@ -175,7 +181,7 @@ struct JNIClassTests {
* }
*/
public static MyClass init(SwiftArena swiftArena$) {
- return new MyClass(MyClass.$init(), swiftArena$);
+ return MyClass.wrapMemoryAddressUnsafe(MyClass.$init(), swiftArena$);
}
""",
"""
@@ -309,7 +315,7 @@ struct JNIClassTests {
* }
*/
public MyClass copy(SwiftArena swiftArena$) {
- return new MyClass(MyClass.$copy(this.$memoryAddress()), swiftArena$);
+ return MyClass.wrapMemoryAddressUnsafe(MyClass.$copy(this.$memoryAddress()), swiftArena$);
}
""",
"""
diff --git a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift
index cd04660b..f9c70ba4 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift
@@ -158,7 +158,7 @@ struct JNIOptionalTests {
public static Optional optionalClass(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(new MyClass(result$, swiftArena$)) : Optional.empty();
+ return (result_discriminator$[0] == 1) ? Optional.of(MyClass.wrapMemoryAddressUnsafe(result$, swiftArena$)) : Optional.empty();
}
""",
"""
diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift
index 01a2e3c0..59d7ee6b 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift
@@ -56,10 +56,16 @@ struct JNIStructTests {
System.loadLibrary(LIB_NAME);
return true;
}
-
- public MyStruct(long selfPointer, SwiftArena swiftArena) {
+ """,
+ """
+ private MyStruct(long selfPointer, SwiftArena swiftArena) {
super(selfPointer, swiftArena);
}
+ """,
+ """
+ public static MyStruct wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
+ return new MyStruct(selfPointer, swiftArena);
+ }
"""
])
try assertOutput(
@@ -110,7 +116,7 @@ struct JNIStructTests {
* }
*/
public static MyStruct init(long x, long y, SwiftArena swiftArena$) {
- return new MyStruct(MyStruct.$init(x, y), swiftArena$);
+ return MyStruct.wrapMemoryAddressUnsafe(MyStruct.$init(x, y), swiftArena$);
}
""",
"""
diff --git a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift
index 4edf59c2..e64d4397 100644
--- a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift
+++ b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift
@@ -43,7 +43,7 @@ struct MemoryManagementModeTests {
* }
*/
public static MyClass f(SwiftArena swiftArena$) {
- return new MyClass(SwiftModule.$f(), swiftArena$);
+ return MyClass.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena$);
}
""",
]
@@ -68,7 +68,7 @@ struct MemoryManagementModeTests {
""",
"""
public static MyClass f(SwiftArena swiftArena$) {
- return new MyClass(SwiftModule.$f(), swiftArena$);
+ return MyClass.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena$);
}
""",
]
diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift
index fd885f1b..3aa7d394 100644
--- a/Tests/JExtractSwiftTests/MethodImportTests.swift
+++ b/Tests/JExtractSwiftTests/MethodImportTests.swift
@@ -227,7 +227,7 @@ final class MethodImportTests {
public static MySwiftClass globalReturnClass(AllocatingSwiftArena swiftArena$) {
MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT);
swiftjava___FakeModule_globalReturnClass.call(_result);
- return new MySwiftClass(_result, swiftArena$);
+ return MySwiftClass.wrapMemoryAddressUnsafe(_result, swiftArena$);
}
"""
)
@@ -404,7 +404,7 @@ final class MethodImportTests {
public static MySwiftClass init(long len, long cap, AllocatingSwiftArena swiftArena$) {
MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT);
swiftjava___FakeModule_MySwiftClass_init_len_cap.call(len, cap, _result)
- return new MySwiftClass(_result, swiftArena$);
+ return MySwiftClass.wrapMemoryAddressUnsafe(_result, swiftArena$);
}
"""
)
@@ -449,7 +449,7 @@ final class MethodImportTests {
public static MySwiftStruct init(long len, long cap, AllocatingSwiftArena swiftArena$) {
MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT);
swiftjava___FakeModule_MySwiftStruct_init_len_cap.call(len, cap, _result)
- return new MySwiftStruct(_result, swiftArena$);
+ return MySwiftStruct.wrapMemoryAddressUnsafe(_result, swiftArena$);
}
"""
)