chinedufn / swift-bridge

swift-bridge facilitates Rust and Swift interop.
https://chinedufn.github.io/swift-bridge
Apache License 2.0
842 stars 62 forks source link

Various errors calling Swift from Rust #201

Open paholg opened 1 year ago

paholg commented 1 year ago

Hello! I am trying to call Swift from Rust, but having a heck of a time getting anything but the most trivial example to work.

In all of the examples below, I have edited src/main.rs and swift-library/Sources/swift-library/swift_library.swift in the rust-binary-calls-swift-package example.


If I try to return an option, like so:

#[swift_bridge::bridge]
mod ffi {
    extern "Swift" {
        fn opt() -> Option<usize>;
    }
}
func opt() -> Optional<UInt> {
    Optional.none
}

I get the following error:

  /Users/paho/git/swift-bridge/examples/rust-binary-calls-swift-package/swift-library/Sources/swift-library/generated/rust-calls-swift/rust-calls-swift.swift:3:31: error: cannot convert return expression of type '__private__OptionUsize' to return type 'UInt'

as well as some warnings about dangling pointers. Looking at the generated code, the generated function is returning a plain UInt:

@_cdecl("__swift_bridge__$opt")
func __swift_bridge__opt () -> UInt {
    { let val = opt(); return __private__OptionUsize(val: val ?? 123, is_some: val != nil); }()
}

If I try to pass a String from Rust to Swift:

#[swift_bridge::bridge]
mod ffi {
    extern "Swift" {
        fn string(str: String);
    }
}
func string(str: RustString) {}

Then I get dangling pointer warnings still, and this error:

  /Users/paho/git/swift-bridge/examples/rust-binary-calls-swift-package/swift-library/Sources/swift-library/generated/rust-calls-swift/rust-calls-swift.swift:2:37: error: cannot find type 'GenericIntoRustString' in scope
  func __swift_bridge__string (_ str: GenericIntoRustString) {
                                      ^~~~~~~~~~~~~~~~~~~~~

Finally, if I try to pass in a Vec (replace String with Vec<usize> and RustString with RustVec<UInt> in the previous example), I get this error:

  /Users/paho/git/swift-bridge/examples/rust-binary-calls-swift-package/swift-library/Sources/swift-library/generated/rust-calls-swift/rust-calls-swift.swift:3:30: error: cannot convert value of type 'RustVec<UInt>' to expected argument type 'UnsafeMutableRawPointer'
      vector(vec: RustVec(ptr: vec))                          ^

I must be doing something simple wrong, but I can't for the life of me figure out what it is, and I would appreciate any help.

chinedufn commented 1 year ago

Hey, thanks for opening this issue.


https://github.com/chinedufn/swift-bridge/pull/202 should fix the dangling pointer warning.


As for the the signatures that you mention, thus far swift-bridge has been biased towards Swift-calling-Rust use cases, mainly because that's my current use case.

That being said, we aim to have excellent bi-directional support, so we want to get these fixed.

If a type is supported in extern "Rust" fns, it should almost always be easy to support the other direction. I'll take a look at your first example now and submit a PR.

chinedufn commented 1 year ago

Submitted a PR for Option<Primitive> in Swift functions https://github.com/chinedufn/swift-bridge/pull/203 .

Mind reviewing it?

paholg commented 1 year ago

Thanks for the quick response! I'll take a look now, though I don't really know swift.