1414
1515import JavaTypes
1616
17- struct JNISwift2JavaGenerator : Swift2JavaGenerator {
17+ class JNISwift2JavaGenerator : Swift2JavaGenerator {
1818 let analysis : AnalysisResult
1919 let swiftModuleName : String
2020 let javaPackage : String
@@ -26,6 +26,8 @@ struct JNISwift2JavaGenerator: Swift2JavaGenerator {
2626 javaPackage. replacingOccurrences ( of: " . " , with: " / " )
2727 }
2828
29+ var thunkNameRegistry = ThunkNameRegistry ( )
30+
2931 init (
3032 translator: Swift2JavaTranslator ,
3133 javaPackage: String ,
@@ -41,6 +43,7 @@ struct JNISwift2JavaGenerator: Swift2JavaGenerator {
4143 }
4244
4345 func generate( ) throws {
46+ try writeSwiftThunkSources ( )
4447 try writeExportedJavaSources ( )
4548 }
4649}
@@ -61,6 +64,84 @@ extension JNISwift2JavaGenerator {
6164 logger. info ( " [swift-java] Generated: \( self . swiftModuleName) .java (at \( outputFile) ) " )
6265 }
6366 }
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+ }
64145}
65146
66147extension JNISwift2JavaGenerator {
@@ -72,6 +153,7 @@ extension JNISwift2JavaGenerator {
72153 for decl in analysis. importedGlobalFuncs {
73154 self . logger. trace ( " Print global function: \( decl) " )
74155 printFunctionBinding ( & printer, decl)
156+ printer. println ( )
75157 }
76158 }
77159 }
@@ -103,10 +185,20 @@ extension JNISwift2JavaGenerator {
103185
104186 private func printFunctionBinding( _ printer: inout CodePrinter , _ decl: ImportedFunc ) {
105187 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 ) ) " ) "
108190 }
109191
192+ printer. print (
193+ """
194+ /**
195+ * Downcall to Swift:
196+ * {@snippet lang=swift :
197+ * \(decl.signatureString)
198+ * }
199+ */
200+ """
201+ )
110202 printer. print ( " public static native \( returnType) \( decl. name) ( \( params. joined ( separator: " , " ) ) ); " )
111203 }
112204}
@@ -128,7 +220,7 @@ extension SwiftType {
128220 return . void
129221
130222 case . metatype, . optional, . tuple, . function:
131- fatalError ( " unsupported " )
223+ fatalError ( " unsupported type: \( self ) " )
132224 }
133225 }
134226}
0 commit comments