Skip to content

Commit 6419865

Browse files
authored
jextract: add support for arrays (#435)
1 parent cafcc1d commit 6419865

File tree

16 files changed

+684
-31
lines changed

16 files changed

+684
-31
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import SwiftJava
16+
17+
public func booleanArray(array: [Bool]) -> [Bool] {
18+
return array
19+
}
20+
21+
public func byteArray(array: [UInt8]) -> [UInt8] {
22+
return array
23+
}
24+
25+
public func byteArrayExplicit(array: Array<UInt8>) -> Array<UInt8> {
26+
return array
27+
}
28+
29+
public func charArray(array: [UInt16]) -> [UInt16] {
30+
return array
31+
}
32+
33+
public func shortArray(array: [Int16]) -> [Int16] {
34+
return array
35+
}
36+
37+
public func intArray(array: [Int32]) -> [Int32] {
38+
return array
39+
}
40+
41+
public func longArray(array: [Int64]) -> [Int64] {
42+
return array
43+
}
44+
45+
public func floatArray(array: [Float]) -> [Float] {
46+
return array
47+
}
48+
49+
public func doubleArray(array: [Double]) -> [Double] {
50+
return array
51+
}
52+
53+
public func stringArray(array: [String]) -> [String] {
54+
return array
55+
}
56+
57+
public func objectArray(array: [MySwiftClass]) -> [MySwiftClass] {
58+
return array
59+
}
60+
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
package com.example.swift;
16+
17+
import org.junit.jupiter.api.Test;
18+
import org.swift.swiftkit.core.SwiftArena;
19+
20+
import java.util.OptionalLong;
21+
import java.util.concurrent.CompletableFuture;
22+
import java.util.concurrent.ExecutionException;
23+
24+
import static org.junit.jupiter.api.Assertions.*;
25+
26+
public class ArraysTest {
27+
@Test
28+
void booleanArray() {
29+
boolean[] input = new boolean[] { true, false, false, true };
30+
assertArrayEquals(input, MySwiftLibrary.booleanArray(input));
31+
}
32+
33+
@Test
34+
void byteArray() {
35+
byte[] input = new byte[] { 10, 20, 30, 40 };
36+
assertArrayEquals(input, MySwiftLibrary.byteArray(input));
37+
}
38+
39+
@Test
40+
void byteArray_empty() {
41+
byte[] input = new byte[] {};
42+
assertArrayEquals(input, MySwiftLibrary.byteArray(input));
43+
}
44+
45+
@Test
46+
void byteArray_null() {
47+
assertThrows(NullPointerException.class, () -> MySwiftLibrary.byteArray(null));
48+
}
49+
50+
@Test
51+
void byteArrayExplicit() {
52+
byte[] input = new byte[] { 10, 20, 30, 40 };
53+
assertArrayEquals(input, MySwiftLibrary.byteArrayExplicit(input));
54+
}
55+
56+
@Test
57+
void charArray() {
58+
char[] input = new char[] { 10, 20, 30, 40 };
59+
assertArrayEquals(input, MySwiftLibrary.charArray(input));
60+
}
61+
62+
@Test
63+
void shortArray() {
64+
short[] input = new short[] { 10, 20, 30, 40 };
65+
assertArrayEquals(input, MySwiftLibrary.shortArray(input));
66+
}
67+
68+
@Test
69+
void intArray() {
70+
int[] input = new int[] { 10, 20, 30, 40 };
71+
assertArrayEquals(input, MySwiftLibrary.intArray(input));
72+
}
73+
74+
@Test
75+
void longArray() {
76+
long[] input = new long[] { 10, 20, 30, 40 };
77+
assertArrayEquals(input, MySwiftLibrary.longArray(input));
78+
}
79+
80+
@Test
81+
void stringArray() {
82+
String[] input = new String[] { "hey", "there", "my", "friend" };
83+
assertArrayEquals(input, MySwiftLibrary.stringArray(input));
84+
}
85+
86+
@Test
87+
void floatArray() {
88+
float[] input = new float[] { 10, 20, 30, 40 };
89+
assertArrayEquals(input, MySwiftLibrary.floatArray(input));
90+
}
91+
92+
@Test
93+
void doubleArray() {
94+
double[] input = new double[] { 10, 20, 30, 40 };
95+
assertArrayEquals(input, MySwiftLibrary.doubleArray(input));
96+
}
97+
98+
@Test
99+
void objectArray() {
100+
try (var arena = SwiftArena.ofConfined()) {
101+
MySwiftClass[] input = new MySwiftClass[]{MySwiftClass.init(arena), MySwiftClass.init(arena), MySwiftClass.init(arena) };
102+
assertEquals(3, MySwiftLibrary.objectArray(input, arena).length);
103+
}
104+
}
105+
}

Sources/JExtractSwiftLib/CodePrinter.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,17 @@ public struct CodePrinter {
8686

8787
public mutating func printBraceBlock(
8888
_ header: Any,
89+
parameters: [String]? = nil,
8990
function: String = #function,
9091
file: String = #fileID,
9192
line: UInt = #line,
9293
body: (inout CodePrinter) throws -> ()
9394
) rethrows {
94-
print("\(header) {")
95+
print("\(header) {", .continue)
96+
if let parameters {
97+
print(" (\(parameters.joined(separator: ", "))) in", .continue)
98+
}
99+
println()
95100
indent()
96101
try body(&self)
97102
outdent()

Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ extension CType {
6868
case .optional(let wrapped) where wrapped.isPointer:
6969
try self.init(cdeclType: wrapped)
7070

71-
case .genericParameter, .metatype, .optional, .tuple, .opaque, .existential, .composite:
71+
case .genericParameter, .metatype, .optional, .tuple, .opaque, .existential, .composite, .array:
7272
throw CDeclToCLoweringError.invalidCDeclType(cdeclType)
7373
}
7474
}
@@ -127,7 +127,7 @@ extension SwiftKnownTypeDeclKind {
127127
case .void: .void
128128
case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer,
129129
.unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .foundationData, .foundationDataProtocol,
130-
.essentialsData, .essentialsDataProtocol, .optional:
130+
.essentialsData, .essentialsDataProtocol, .optional, .array:
131131
nil
132132
}
133133
}

Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ struct CdeclLowering {
347347

348348
case .composite:
349349
throw LoweringError.unhandledType(type)
350+
351+
case .array:
352+
throw LoweringError.unhandledType(type)
350353
}
351354
}
352355

@@ -415,7 +418,7 @@ struct CdeclLowering {
415418
}
416419
throw LoweringError.unhandledType(.optional(wrappedType))
417420

418-
case .function, .metatype, .optional, .composite:
421+
case .function, .metatype, .optional, .composite, .array:
419422
throw LoweringError.unhandledType(.optional(wrappedType))
420423
}
421424
}
@@ -516,7 +519,7 @@ struct CdeclLowering {
516519
// Custom types are not supported yet.
517520
throw LoweringError.unhandledType(type)
518521

519-
case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite:
522+
case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite, .array:
520523
// TODO: Implement
521524
throw LoweringError.unhandledType(type)
522525
}
@@ -670,7 +673,7 @@ struct CdeclLowering {
670673
conversion: .tupleExplode(conversions, name: outParameterName)
671674
)
672675

673-
case .genericParameter, .function, .optional, .existential, .opaque, .composite:
676+
case .genericParameter, .function, .optional, .existential, .opaque, .composite, .array:
674677
throw LoweringError.unhandledType(type)
675678
}
676679
}

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,9 @@ extension FFMSwift2JavaGenerator {
475475

476476
case .composite:
477477
throw JavaTranslationError.unhandledType(swiftType)
478+
479+
case .array(let elementType):
480+
throw JavaTranslationError.unhandledType(swiftType)
478481
}
479482
}
480483

@@ -694,7 +697,7 @@ extension FFMSwift2JavaGenerator {
694697
// TODO: Implement.
695698
throw JavaTranslationError.unhandledType(swiftType)
696699

697-
case .genericParameter, .optional, .function, .existential, .opaque, .composite:
700+
case .genericParameter, .optional, .function, .existential, .opaque, .composite, .array:
698701
throw JavaTranslationError.unhandledType(swiftType)
699702
}
700703

Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@ enum JNIJavaTypeTranslator {
4545
case .void: return .void
4646

4747
case .string: return .javaLangString
48+
4849
case .int, .uint, // FIXME: why not supported int/uint?
4950
.unsafeRawPointer, .unsafeMutableRawPointer,
5051
.unsafePointer, .unsafeMutablePointer,
5152
.unsafeRawBufferPointer, .unsafeMutableRawBufferPointer,
5253
.unsafeBufferPointer, .unsafeMutableBufferPointer,
53-
.optional, .foundationData, .foundationDataProtocol, .essentialsData, .essentialsDataProtocol:
54+
.optional, .foundationData, .foundationDataProtocol, .essentialsData, .essentialsDataProtocol, .array:
5455
return nil
5556
}
5657
}
57-
}
58+
}

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ extension JNISwift2JavaGenerator {
2525
"java.util.concurrent.atomic.AtomicBoolean",
2626

2727
// NonNull, Unsigned and friends
28-
"org.swift.swiftkit.core.annotations.*",
28+
"org.swift.swiftkit.core.annotations.*"
2929
]
3030
}
3131

0 commit comments

Comments
 (0)