Skip to content

Unable to bridge async function that returns Vec #344

Description

@crwen

I tried to call an asynchronous function returning Vec<u8> from Rust in Swift, but I got the following errors when compile with swiftc:

error: cannot convert value of type 'RustVec<UInt8>' to expected argument type 'UnsafeMutableRawPointer'
 2 |     func onComplete(cbWrapperPtr: UnsafeMutableRawPointer?, rustFnRetVal: RustVec<UInt8>) {
 3 |         let wrapper = Unmanaged<CbWrapper$async_func_return_vec>.fromOpaque(cbWrapperPtr!).takeRetainedValue()
 4 |         wrapper.cb(.success(RustVec(ptr: rustFnRetVal)))
   |                                          `- error: cannot convert value of type 'RustVec<UInt8>' to expected argument type 'UnsafeMutableRawPointer'
 5 |     }
 6 | 

error: cannot convert value of type '(UnsafeMutableRawPointer?, RustVec<UInt8>) -> ()' to expected argument type '(@convention(c) (UnsafeMutableRawPointer?, UnsafeMutableRawPointer?) -> Void)?'
13 |         let wrapperPtr = Unmanaged.passRetained(wrapper).toOpaque()
14 | 
15 |         __swift_bridge__$async_func_return_vec(wrapperPtr, onComplete)
   |                                                            `- error: cannot convert value of type '(UnsafeMutableRawPointer?, RustVec<UInt8>) -> ()' to expected argument type '(@convention(c) (UnsafeMutableRawPointer?, UnsafeMutableRawPointer?) -> Void)?'
16 |     })
17 | }

I think the problem is that the function signature of the onComplete callback does not match the function signature of the generated c header file.

Here is the minimal reproducible example
// lib.rs

#[swift_bridge::bridge]
mod ffi {
    extern "Rust" {
        async fn async_func_return_vec() -> Vec<u8>;
    }
}

async fn async_func_return_vec() -> Vec<u8> {
    vec![1, 2, 3]
}

Here is the generated swift code:

public func async_func_return_vec() async -> RustVec<UInt8> {
    func onComplete(cbWrapperPtr: UnsafeMutableRawPointer?, rustFnRetVal: RustVec<UInt8>) {
        let wrapper = Unmanaged<CbWrapper$async_func_return_vec>.fromOpaque(cbWrapperPtr!).takeRetainedValue()
        wrapper.cb(.success(RustVec(ptr: rustFnRetVal)))
    }

    return await withCheckedContinuation({ (continuation: CheckedContinuation<RustVec<UInt8>, Never>) in
        let callback = { rustFnRetVal in
            continuation.resume(with: rustFnRetVal)
        }

        let wrapper = CbWrapper$async_func_return_vec(cb: callback)
        let wrapperPtr = Unmanaged.passRetained(wrapper).toOpaque()

        __swift_bridge__$async_func_return_vec(wrapperPtr, onComplete)
    })
}

Here is the generated c header code:

void __swift_bridge__$async_func_return_vec(void* callback_wrapper, void __swift_bridge__$async_func_return_vec$async(void* callback_wrapper, void* ret));

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions