Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various errors calling Swift from Rust #201

Open
paholg opened this issue Mar 18, 2023 · 3 comments
Open

Various errors calling Swift from Rust #201

paholg opened this issue Mar 18, 2023 · 3 comments

Comments

@paholg
Copy link

paholg commented Mar 18, 2023

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
Copy link
Owner

Hey, thanks for opening this issue.


#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
Copy link
Owner

Submitted a PR for Option<Primitive> in Swift functions #203 .

Mind reviewing it?

@paholg
Copy link
Author

paholg commented Mar 19, 2023

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

chinedufn pushed a commit that referenced this issue Jun 23, 2023
Related to #201. This commit adds support `RustString`  in extern Swift functions.

Here's an example of using this.

```Swift
//Swift
func reflect_swift_string(arg: RustString) -> RustString {
    arg
}

```

```Rust
//Rust
#[swift_bridge::bridge]
mod ffi {
    extern "Swift" {
        fn reflect_swift_string(arg: String) -> String;
    }
}

let foo = "foo";
let string = ffi::reflect_swift_string(foo.to_string());
assert_eq!(string.len(), 3);
assert_eq!(&string, foo);
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants