14
14
15
15
import JavaTypes
16
16
17
- struct JNISwift2JavaGenerator : Swift2JavaGenerator {
17
+ class JNISwift2JavaGenerator : Swift2JavaGenerator {
18
18
let analysis : AnalysisResult
19
19
let swiftModuleName : String
20
20
let javaPackage : String
@@ -26,6 +26,8 @@ struct JNISwift2JavaGenerator: Swift2JavaGenerator {
26
26
javaPackage. replacingOccurrences ( of: " . " , with: " / " )
27
27
}
28
28
29
+ var thunkNameRegistry = ThunkNameRegistry ( )
30
+
29
31
init (
30
32
translator: Swift2JavaTranslator ,
31
33
javaPackage: String ,
@@ -41,6 +43,7 @@ struct JNISwift2JavaGenerator: Swift2JavaGenerator {
41
43
}
42
44
43
45
func generate( ) throws {
46
+ try writeSwiftThunkSources ( )
44
47
try writeExportedJavaSources ( )
45
48
}
46
49
}
@@ -61,6 +64,84 @@ extension JNISwift2JavaGenerator {
61
64
logger. info ( " [swift-java] Generated: \( self . swiftModuleName) .java (at \( outputFile) ) " )
62
65
}
63
66
}
67
+
68
+ func writeSwiftThunkSources( ) throws {
69
+ var printer = CodePrinter ( )
70
+
71
+ let moduleFilenameBase = " \( self . swiftModuleName) Module+SwiftJava "
72
+ let moduleFilename = " \( moduleFilenameBase) .swift "
73
+
74
+ logger. trace ( " Printing swift module class: \( moduleFilename) " )
75
+
76
+ try printGlobalSwiftThunkSources ( & printer)
77
+
78
+ if let outputFile = try printer. writeContents (
79
+ outputDirectory: self . swiftOutputDirectory,
80
+ javaPackagePath: nil ,
81
+ filename: moduleFilename)
82
+ {
83
+ print ( " [swift-java] Generated: \( moduleFilenameBase. bold) .swift (at \( outputFile) " )
84
+ }
85
+ }
86
+ }
87
+
88
+ extension JNISwift2JavaGenerator {
89
+ private func printGlobalSwiftThunkSources( _ printer: inout CodePrinter ) throws {
90
+ printer. print (
91
+ """
92
+ // Generated by swift-java
93
+
94
+ import JavaKit
95
+
96
+ """ )
97
+
98
+ for decl in analysis. importedGlobalFuncs {
99
+ printSwiftFunctionThunk ( & printer, decl)
100
+ printer. println ( )
101
+ }
102
+ }
103
+
104
+ private func printSwiftFunctionThunk( _ printer: inout CodePrinter , _ decl: ImportedFunc ) {
105
+ // TODO: Replace swiftModuleName with class name if non-global
106
+ let cName = " Java_ " + self . javaPackage. replacingOccurrences ( of: " . " , with: " _ " ) + " _ \( swiftModuleName) _ " + decl. name
107
+ let thunkName = thunkNameRegistry. functionThunkName ( decl: decl)
108
+ let translatedParameters = decl. functionSignature. parameters. enumerated ( ) . map { idx, param in
109
+ ( param. parameterName ?? " arg \( idx) " , param. type. javaType)
110
+ }
111
+
112
+ let thunkParameters = [
113
+ " environment: UnsafeMutablePointer<JNIEnv?>! " ,
114
+ " thisClass: jclass "
115
+ ] + translatedParameters. map { " \( $0. 0 ) : \( $0. 1 . jniTypeName) " }
116
+ let swiftReturnType = decl. functionSignature. result. type
117
+
118
+ let thunkReturnType = !swiftReturnType. isVoid ? " -> \( swiftReturnType. javaType. jniTypeName) " : " "
119
+
120
+ printer. printBraceBlock (
121
+ """
122
+ @_cdecl( " \( cName) " )
123
+ func \( thunkName) ( \( thunkParameters. joined ( separator: " , " ) ) ) \( thunkReturnType)
124
+ """
125
+ ) { printer in
126
+ let downcallParameters = zip ( decl. functionSignature. parameters, translatedParameters) . map { originalParam, translatedParam in
127
+ let label = originalParam. argumentLabel ?? originalParam. parameterName ?? " "
128
+ return " \( label) \( !label. isEmpty ? " : " : " " ) \( translatedParam. 0 ) "
129
+ }
130
+ let functionDowncall = " \( swiftModuleName) . \( decl. name) ( \( downcallParameters. joined ( separator: " , " ) ) ) "
131
+ printer. print ( " \( functionDowncall) " )
132
+
133
+ if swiftReturnType. isVoid {
134
+ printer. print ( functionDowncall)
135
+ } else {
136
+ printer. print (
137
+ """
138
+ let result = \( functionDowncall)
139
+ return result.getJNIValue(in: environment) " )
140
+ """
141
+ )
142
+ }
143
+ }
144
+ }
64
145
}
65
146
66
147
extension JNISwift2JavaGenerator {
@@ -72,6 +153,7 @@ extension JNISwift2JavaGenerator {
72
153
for decl in analysis. importedGlobalFuncs {
73
154
self . logger. trace ( " Print global function: \( decl) " )
74
155
printFunctionBinding ( & printer, decl)
156
+ printer. println ( )
75
157
}
76
158
}
77
159
}
@@ -103,10 +185,20 @@ extension JNISwift2JavaGenerator {
103
185
104
186
private func printFunctionBinding( _ printer: inout CodePrinter , _ decl: ImportedFunc ) {
105
187
let returnType = decl. functionSignature. result. type. javaType
106
- let params = decl. functionSignature. parameters. map {
107
- " \( $0 . type. javaType) \( $0 . parameterName! ) "
188
+ let params = decl. functionSignature. parameters. enumerated ( ) . map { idx , param in
189
+ " \( param . type. javaType) \( param . parameterName ?? " arg \( idx ) ) " ) "
108
190
}
109
191
192
+ printer. print (
193
+ """
194
+ /**
195
+ * Downcall to Swift:
196
+ * {@snippet lang=swift :
197
+ * \(decl.signatureString)
198
+ * }
199
+ */
200
+ """
201
+ )
110
202
printer. print ( " public static native \( returnType) \( decl. name) ( \( params. joined ( separator: " , " ) ) ); " )
111
203
}
112
204
}
@@ -128,7 +220,7 @@ extension SwiftType {
128
220
return . void
129
221
130
222
case . metatype, . optional, . tuple, . function:
131
- fatalError ( " unsupported " )
223
+ fatalError ( " unsupported type: \( self ) " )
132
224
}
133
225
}
134
226
}
0 commit comments