Skip to content

Commit 7860cb8

Browse files
committed
[JExtract] Import any C compatible closure
Generalized closure parameter import, part 1. Start with C-compatible closures which don't need any conversions.
1 parent eff20b9 commit 7860cb8

File tree

14 files changed

+591
-126
lines changed

14 files changed

+591
-126
lines changed

Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ void call_globalTakeInt() {
4343
void call_globalCallMeRunnable() {
4444
CountDownLatch countDownLatch = new CountDownLatch(3);
4545

46-
MySwiftLibrary.globalCallMeRunnable(new Runnable() {
46+
MySwiftLibrary.globalCallMeRunnable(new MySwiftLibrary.globalCallMeRunnable.run() {
4747
@Override
48-
public void run() {
48+
public void apply() {
4949
countDownLatch.countDown();
5050
}
5151
});

Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public struct MySwiftStruct {
4848
self.len
4949
}
5050

51+
public func withCapLen(_ body: (Int, Int) -> Void) {
52+
body(cap, len)
53+
}
54+
5155
public mutating func increaseCap(by value: Int) -> Int {
5256
precondition(value > 0)
5357
self.cap += value

Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ static void examples() {
6767

6868
MySwiftStruct swiftValue = MySwiftStruct.init(2222, 1111, arena);
6969
SwiftKit.trace("swiftValue.capacity = " + swiftValue.getCapacity());
70+
swiftValue.withCapLen((cap, len) -> {
71+
SwiftKit.trace("withCapLenCallback: cap=" + cap + ", len=" + len);
72+
});
7073
}
7174

7275
System.out.println("DONE.");

Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ void call_writeString_jni() {
6464
void call_globalCallMeRunnable() {
6565
CountDownLatch countDownLatch = new CountDownLatch(3);
6666

67-
MySwiftLibrary.globalCallMeRunnable(new Runnable() {
67+
MySwiftLibrary.globalCallMeRunnable(new MySwiftLibrary.globalCallMeRunnable.run() {
6868
@Override
69-
public void run() {
69+
public void apply() {
7070
countDownLatch.countDown();
7171
}
7272
});

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

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ struct CdeclLowering {
116116
)
117117
}
118118

119-
/// Lower a Swift function parameter type to cdecl parameters.
119+
/// Lower a Swift function parameter to cdecl parameters.
120120
///
121121
/// For example, Swift parameter `arg value: inout Int` can be lowered with
122122
/// `lowerParameter(intTy, .inout, "value")`.
@@ -276,25 +276,63 @@ struct CdeclLowering {
276276
}
277277
return LoweredParameter(cdeclParameters: parameters, conversion: .tuplify(conversions))
278278

279-
case .function(let fn) where fn.parameters.isEmpty && fn.resultType.isVoid:
279+
case .function(let fn):
280+
let (loweredTy, conversion) = try lowerFunctionType(fn)
280281
return LoweredParameter(
281282
cdeclParameters: [
282283
SwiftParameter(
283284
convention: .byValue,
284285
parameterName: parameterName,
285-
type: .function(SwiftFunctionType(convention: .c, parameters: [], resultType: fn.resultType))
286+
type: loweredTy
286287
)
287288
],
288-
// '@convention(c) () -> ()' is compatible with '() -> Void'.
289-
conversion: .placeholder
289+
conversion: conversion
290290
)
291291

292-
case .function, .optional:
293-
// FIXME: Support other function types than '() -> Void'.
292+
case .optional:
294293
throw LoweringError.unhandledType(type)
295294
}
296295
}
297296

297+
/// Lower a Swift function type (i.e. closure) to cdecl function type.
298+
///
299+
/// - Parameters:
300+
/// - fn: the Swift function type to lower.
301+
func lowerFunctionType(
302+
_ fn: SwiftFunctionType
303+
) throws -> (type: SwiftType, conversion: ConversionStep) {
304+
var parameters: [SwiftParameter] = []
305+
var parameterConversions: [ConversionStep] = []
306+
307+
for parameter in fn.parameters {
308+
if let _ = try? CType(cdeclType: parameter.type) {
309+
parameters.append(SwiftParameter(convention: .byValue, type: parameter.type))
310+
parameterConversions.append(.placeholder)
311+
} else {
312+
// Non-trivial types are not yet supported.
313+
throw LoweringError.unhandledType(.function(fn))
314+
}
315+
}
316+
317+
let resultType: SwiftType
318+
let resultConversion: ConversionStep
319+
if let _ = try? CType(cdeclType: fn.resultType) {
320+
resultType = fn.resultType
321+
resultConversion = .placeholder
322+
} else {
323+
// Non-trivial types are not yet supported.
324+
throw LoweringError.unhandledType(.function(fn))
325+
}
326+
327+
// Ignore the conversions for now, since we don't support non-trivial types yet.
328+
_ = (parameterConversions, resultConversion)
329+
330+
return (
331+
type: .function(SwiftFunctionType(convention: .c, parameters: parameters, resultType: resultType)),
332+
conversion: .placeholder
333+
)
334+
}
335+
298336
/// Lower a Swift result type to cdecl out parameters and return type.
299337
///
300338
/// - Parameters:

0 commit comments

Comments
 (0)