Skip to content

Commit 42fc103

Browse files
committed
Adding FfiType::Handle and use it for Rust futures
FfiType::Handle is a opaque 64-bit handle that's used to pass objects across the FFI. This PR changes the rustfuture code to use it and also renames the type used to represent callback interfaces from `u64` to handle. The plan is to use it for all object types, including interfaces and trait interfaces, but that will be done in future PRs. Accompianing that code is the `HandleAlloc` trait, which has a general system for allocating/using/freeing handles for objects. It's essentially the same system(s) we're currently using, but now the code is all in one place. On the bindings side, switched the code to using the `u64` type rather than having a `UniffiHandle` type alias. I don't think the type alias is very useful since handles are only used internally. Also, I remember running into Swift issues with the type alias and multiple crates. Most of this code was copied from the handles PR (#1823).
1 parent 132635c commit 42fc103

File tree

22 files changed

+271
-96
lines changed

22 files changed

+271
-96
lines changed

uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ impl KotlinCodeOracle {
370370
FfiType::Int64 | FfiType::UInt64 => "Long".to_string(),
371371
FfiType::Float32 => "Float".to_string(),
372372
FfiType::Float64 => "Double".to_string(),
373+
FfiType::Handle => "Long".to_string(),
373374
FfiType::RustArcPtr(_) => "Pointer".to_string(),
374375
FfiType::RustBuffer(maybe_suffix) => {
375376
format!("RustBuffer{}", maybe_suffix.as_deref().unwrap_or_default())
@@ -378,7 +379,7 @@ impl KotlinCodeOracle {
378379
FfiType::Callback(name) => self.ffi_callback_name(name),
379380
FfiType::Struct(name) => self.ffi_struct_name(name),
380381
FfiType::Reference(inner) => self.ffi_type_label_by_reference(inner),
381-
FfiType::VoidPointer | FfiType::RustFutureHandle => "Pointer".to_string(),
382+
FfiType::VoidPointer => "Pointer".to_string(),
382383
}
383384
}
384385

uniffi_bindgen/src/bindings/kotlin/templates/Async.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ internal object uniffiRustFutureContinuationCallback: UniffiRustFutureContinuati
1313
}
1414

1515
internal suspend fun<T, F, E: Exception> uniffiRustCallAsync(
16-
rustFuture: Pointer,
17-
pollFunc: (Pointer, UniffiRustFutureContinuationCallback, Long) -> Unit,
18-
completeFunc: (Pointer, UniffiRustCallStatus) -> F,
19-
freeFunc: (Pointer) -> Unit,
16+
rustFuture: Long,
17+
pollFunc: (Long, UniffiRustFutureContinuationCallback, Long) -> Unit,
18+
completeFunc: (Long, UniffiRustCallStatus) -> F,
19+
freeFunc: (Long) -> Unit,
2020
liftFunc: (F) -> T,
2121
errorHandler: UniffiRustCallStatusErrorHandler<E>
2222
): T {

uniffi_bindgen/src/bindings/kotlin/templates/CallbackInterfaceRuntime.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ internal const val UNIFFI_CALLBACK_SUCCESS = 0
66
internal const val UNIFFI_CALLBACK_ERROR = 1
77
internal const val UNIFFI_CALLBACK_UNEXPECTED_ERROR = 2
88

9-
public abstract class FfiConverterCallbackInterface<CallbackInterface: Any>: FfiConverter<CallbackInterface, UniffiHandle> {
9+
public abstract class FfiConverterCallbackInterface<CallbackInterface: Any>: FfiConverter<CallbackInterface, Long> {
1010
internal val handleMap = UniffiHandleMap<CallbackInterface>()
1111

12-
internal fun drop(handle: UniffiHandle) {
12+
internal fun drop(handle: Long) {
1313
handleMap.remove(handle)
1414
}
1515

16-
override fun lift(value: UniffiHandle): CallbackInterface {
16+
override fun lift(value: Long): CallbackInterface {
1717
return handleMap.get(value)
1818
}
1919

uniffi_bindgen/src/bindings/kotlin/templates/CallbackInterfaceTemplate.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
{% include "Interface.kt" %}
1010
{% include "CallbackInterfaceImpl.kt" %}
1111

12-
// The ffiConverter which transforms the Callbacks in to UniffiHandles to pass to Rust.
12+
// The ffiConverter which transforms the Callbacks in to handles to pass to Rust.
1313
public object {{ ffi_converter_name }}: FfiConverterCallbackInterface<{{ interface_name }}>()
Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,27 @@
1-
// Handle from a UniffiHandleMap
2-
internal typealias UniffiHandle = Long
3-
41
// Map handles to objects
52
//
63
// This is used pass an opaque 64-bit handle representing a foreign object to the Rust code.
74
internal class UniffiHandleMap<T: Any> {
8-
private val map = ConcurrentHashMap<UniffiHandle, T>()
5+
private val map = ConcurrentHashMap<Long, T>()
96
private val counter = java.util.concurrent.atomic.AtomicLong(0)
107

118
val size: Int
129
get() = map.size
1310

1411
// Insert a new object into the handle map and get a handle for it
15-
fun insert(obj: T): UniffiHandle {
12+
fun insert(obj: T): Long {
1613
val handle = counter.getAndAdd(1)
1714
map.put(handle, obj)
1815
return handle
1916
}
2017

2118
// Get an object from the handle map
22-
fun get(handle: UniffiHandle): T {
19+
fun get(handle: Long): T {
2320
return map.get(handle) ?: throw InternalException("UniffiHandleMap.get: Invalid handle")
2421
}
2522

2623
// Remove an entry from the handlemap and get the Kotlin object back
27-
fun remove(handle: UniffiHandle): T {
24+
fun remove(handle: Long): T {
2825
return map.remove(handle) ?: throw InternalException("UniffiHandleMap: Invalid handle")
2926
}
3027
}

uniffi_bindgen/src/bindings/python/gen_python/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ impl PythonCodeOracle {
361361
FfiType::UInt64 => "ctypes.c_uint64".to_string(),
362362
FfiType::Float32 => "ctypes.c_float".to_string(),
363363
FfiType::Float64 => "ctypes.c_double".to_string(),
364+
FfiType::Handle => "ctypes.c_uint64".to_string(),
364365
FfiType::RustArcPtr(_) => "ctypes.c_void_p".to_string(),
365366
FfiType::RustBuffer(maybe_suffix) => match maybe_suffix {
366367
Some(suffix) => format!("_UniffiRustBuffer{suffix}"),
@@ -371,7 +372,7 @@ impl PythonCodeOracle {
371372
FfiType::Struct(name) => self.ffi_struct_name(name),
372373
// Pointer to an `asyncio.EventLoop` instance
373374
FfiType::Reference(inner) => format!("ctypes.POINTER({})", self.ffi_type_label(inner)),
374-
FfiType::VoidPointer | FfiType::RustFutureHandle => "ctypes.c_void_p".to_string(),
375+
FfiType::VoidPointer => "ctypes.c_void_p".to_string(),
375376
}
376377
}
377378

uniffi_bindgen/src/bindings/ruby/gen_ruby/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ mod filters {
149149
FfiType::UInt64 => ":uint64".to_string(),
150150
FfiType::Float32 => ":float".to_string(),
151151
FfiType::Float64 => ":double".to_string(),
152+
FfiType::Handle => ":uint64".to_string(),
152153
FfiType::RustArcPtr(_) => ":pointer".to_string(),
153154
FfiType::RustBuffer(_) => "RustBuffer.by_value".to_string(),
154155
FfiType::ForeignBytes => "ForeignBytes".to_string(),
@@ -162,9 +163,6 @@ mod filters {
162163
FfiType::Struct(_) => {
163164
unimplemented!("Structs are not implemented")
164165
}
165-
FfiType::RustFutureHandle => {
166-
unimplemented!("Async functions are not implemented")
167-
}
168166
})
169167
}
170168

uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ impl SwiftCodeOracle {
529529
FfiType::UInt64 => "UInt64".into(),
530530
FfiType::Float32 => "Float".into(),
531531
FfiType::Float64 => "Double".into(),
532+
FfiType::Handle => "UInt64".into(),
532533
FfiType::RustArcPtr(_) => "UnsafeMutableRawPointer".into(),
533534
FfiType::RustBuffer(_) => "RustBuffer".into(),
534535
FfiType::ForeignBytes => "ForeignBytes".into(),
@@ -537,7 +538,7 @@ impl SwiftCodeOracle {
537538
FfiType::Reference(inner) => {
538539
format!("UnsafeMutablePointer<{}>", self.ffi_type_label(inner))
539540
}
540-
FfiType::VoidPointer | FfiType::RustFutureHandle => "UnsafeMutableRawPointer".into(),
541+
FfiType::VoidPointer => "UnsafeMutableRawPointer".into(),
541542
}
542543
}
543544

@@ -630,6 +631,7 @@ pub mod filters {
630631
FfiType::UInt64 => "uint64_t".into(),
631632
FfiType::Float32 => "float".into(),
632633
FfiType::Float64 => "double".into(),
634+
FfiType::Handle => "uint64_t".into(),
633635
FfiType::RustArcPtr(_) => "void*_Nonnull".into(),
634636
FfiType::RustBuffer(_) => "RustBuffer".into(),
635637
FfiType::ForeignBytes => "ForeignBytes".into(),
@@ -638,7 +640,7 @@ pub mod filters {
638640
}
639641
FfiType::Struct(name) => SwiftCodeOracle.ffi_struct_name(name),
640642
FfiType::Reference(inner) => format!("{}* _Nonnull", header_ffi_type_name(inner)?),
641-
FfiType::VoidPointer | FfiType::RustFutureHandle => "void* _Nonnull".into(),
643+
FfiType::VoidPointer => "void* _Nonnull".into(),
642644
})
643645
}
644646

uniffi_bindgen/src/bindings/swift/templates/Async.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ private let UNIFFI_RUST_FUTURE_POLL_MAYBE_READY: Int8 = 1
44
fileprivate let uniffiContinuationHandleMap = UniffiHandleMap<UnsafeContinuation<Int8, Never>>()
55

66
fileprivate func uniffiRustCallAsync<F, T>(
7-
rustFutureFunc: () -> UnsafeMutableRawPointer,
8-
pollFunc: (UnsafeMutableRawPointer, @escaping UniffiRustFutureContinuationCallback, UInt64) -> (),
9-
completeFunc: (UnsafeMutableRawPointer, UnsafeMutablePointer<RustCallStatus>) -> F,
10-
freeFunc: (UnsafeMutableRawPointer) -> (),
7+
rustFutureFunc: () -> UInt64,
8+
pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> (),
9+
completeFunc: (UInt64, UnsafeMutablePointer<RustCallStatus>) -> F,
10+
freeFunc: (UInt64) -> (),
1111
liftFunc: (F) throws -> T,
1212
errorHandler: ((RustBuffer) throws -> Error)?
1313
) async throws -> T {

uniffi_bindgen/src/bindings/swift/templates/CallbackInterfaceTemplate.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,18 @@ fileprivate struct {{ ffi_converter_name }} {
1818

1919
extension {{ ffi_converter_name }} : FfiConverter {
2020
typealias SwiftType = {{ type_name }}
21-
// We can use Handle as the FfiType because it's a typealias to UInt64
22-
typealias FfiType = UniffiHandle
21+
typealias FfiType = UInt64
2322

24-
public static func lift(_ handle: UniffiHandle) throws -> SwiftType {
23+
public static func lift(_ handle: UInt64) throws -> SwiftType {
2524
try handleMap.get(handle: handle)
2625
}
2726

2827
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
29-
let handle: UniffiHandle = try readInt(&buf)
28+
let handle: UInt64 = try readInt(&buf)
3029
return try lift(handle)
3130
}
3231

33-
public static func lower(_ v: SwiftType) -> UniffiHandle {
32+
public static func lower(_ v: SwiftType) -> UInt64 {
3433
return handleMap.insert(obj: v)
3534
}
3635

0 commit comments

Comments
 (0)