Skip to content

Commit e887a9f

Browse files
authored
[JExtract] Generate JNI code for classes (static methods and initializers) (#298)
1 parent 56dfcfa commit e887a9f

18 files changed

+1444
-721
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
public class MySwiftClass {
16+
let x: Int64
17+
let y: Int64
18+
19+
public static func method() {
20+
p("Hello from static method in a class!")
21+
}
22+
23+
public init(x: Int64, y: Int64) {
24+
self.x = x
25+
self.y = y
26+
p("\(self)")
27+
}
28+
29+
public init() {
30+
self.x = 10
31+
self.y = 5
32+
}
33+
34+
deinit {
35+
p("deinit called!")
36+
}
37+
}

Samples/JExtractJNISampleApp/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ dependencies {
156156

157157
tasks.named('test', Test) {
158158
useJUnitPlatform()
159+
160+
testLogging {
161+
events "failed"
162+
exceptionFormat "full"
163+
}
159164
}
160165

161166
application {

Samples/JExtractJNISampleApp/ci-validate.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
set -x
44
set -e
55

6-
./gradlew run
6+
./gradlew run
7+
./gradlew test

Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ static void examples() {
4040
long i = MySwiftLibrary.globalMakeInt();
4141
SwiftKit.trace("globalMakeInt() = " + i);
4242

43+
MySwiftClass.method();
44+
45+
MySwiftClass myClass = MySwiftClass.init(10, 5);
46+
MySwiftClass myClass2 = MySwiftClass.init();
47+
4348
System.out.println("DONE.");
4449
}
4550
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 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 com.example.swift.MySwiftLibrary;
18+
import org.junit.jupiter.api.BeforeAll;
19+
import org.junit.jupiter.api.Disabled;
20+
import org.junit.jupiter.api.Test;
21+
22+
import static org.junit.jupiter.api.Assertions.*;
23+
24+
public class MySwiftClassTest {
25+
@Test
26+
void init_noParameters() {
27+
MySwiftClass c = MySwiftClass.init();
28+
assertNotNull(c);
29+
}
30+
31+
@Test
32+
void init_withParameters() {
33+
MySwiftClass c = MySwiftClass.init(1337, 42);
34+
assertNotNull(c);
35+
}
36+
37+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 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 com.example.swift.MySwiftLibrary;
18+
import org.junit.jupiter.api.BeforeAll;
19+
import org.junit.jupiter.api.Disabled;
20+
import org.junit.jupiter.api.Test;
21+
22+
import java.util.Arrays;
23+
import java.util.concurrent.CountDownLatch;
24+
import java.util.stream.Collectors;
25+
26+
import static org.junit.jupiter.api.Assertions.*;
27+
28+
public class MySwiftLibraryTest {
29+
@Test
30+
void call_helloWorld() {
31+
MySwiftLibrary.helloWorld();
32+
}
33+
34+
@Test
35+
void call_globalTakeInt() {
36+
MySwiftLibrary.globalTakeInt(12);
37+
}
38+
39+
@Test
40+
void call_globalMakeInt() {
41+
long i = MySwiftLibrary.globalMakeInt();
42+
assertEquals(42, i);
43+
}
44+
45+
@Test
46+
void call_globalTakeIntInt() {
47+
MySwiftLibrary.globalTakeIntInt(1337, 42);
48+
}
49+
50+
@Test
51+
void call_writeString_jextract() {
52+
var string = "Hello Swift!";
53+
long reply = MySwiftLibrary.globalWriteString(string);
54+
55+
assertEquals(string.length(), reply);
56+
}
57+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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 JavaTypes
16+
17+
extension JavaType {
18+
var jniTypeSignature: String {
19+
switch self {
20+
case .boolean: "Z"
21+
case .byte: "B"
22+
case .char: "C"
23+
case .short: "S"
24+
case .int: "I"
25+
case .long: "J"
26+
case .float: "F"
27+
case .double: "D"
28+
case .class(let package, let name):
29+
if let package {
30+
"L\(package.replacingOccurrences(of: ".", with: "/"))/\(name);"
31+
} else {
32+
"L\(name);"
33+
}
34+
case .array(let javaType): "[\(javaType.jniTypeSignature)"
35+
case .void: fatalError("There is no type signature for 'void'")
36+
}
37+
}
38+
}

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ extension FFMSwift2JavaGenerator {
439439
}
440440
}
441441

442-
extension JavaConversionStep {
442+
extension FFMSwift2JavaGenerator.JavaConversionStep {
443443
/// Whether the conversion uses SwiftArena.
444444
var requiresSwiftArena: Bool {
445445
switch self {

0 commit comments

Comments
 (0)