-
Notifications
You must be signed in to change notification settings - Fork 53
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
Add RustVec<T>.as_ptr() -> UnsafePointer<T>
method
#214
Comments
Thanks for the detailed issue and examples. I'm not understanding what you mean by Option 2? Can you illustrate what you mean with code like you did for Option 1? If possible, can you also include a snippet of the code that is using the |
I don't have code for Option 2 since I couldn't figure it out, but it would basically be the rust function returning a Vec that I could somehow load into a https://github.com/aiongg/khiin-rs/blob/master/swift/EngineBindings/src/lib.rs https://github.com/aiongg/khiin-rs/blob/master/swift/EngineBindings/EngineController.swift https://github.com/aiongg/khiin-rs/blob/master/swift/EngineBindings/generated/khiin_swift.h |
Thanks for the links
Can you write a snippet showing, roughly, how you would want the bridge module signature to look? It may sound unnecessary, but I'm asking because I've found that talking in terms of bridge modules reduces cognitive load substantially and gets us on the exact same page. i.e. something like: // Rust
#[swift_bridge::bridge]
mod ffi {
extern "Rust" {
// ... the signature that you want to support
}
}
Gotcha. It looks like So, if you had a way to get the pointer to the first byte in the |
(Sorry I first posted from another device where I was logged in to a different account.) Sure, well the ideal signature would be bytes-in-bytes-out: fn send_command(command_bytes: &[u8]) -> Option<Vec<u8>>; with no length counting or in-out params at all. This is identical to the actual method I use in the cross-platform library, seen here: https://github.com/aiongg/khiin-rs/blob/master/khiin/src/engine.rs#L51 So in that case my FFI code would be one-liner, which would be great. As I mentioned I'm new to Swift so I'm not positive, but it seems like the pointer and length would be sufficient for a This would make it very straightforward for anyone else using protobuf to pass arbitrary data between rust and swift without any additional setup, since protobuf is just a serializer/deserializer to bytes. |
Ok, cool. In that case, it looks like the signature that you want is already supported, so it sounds like the solution here is to expose a method to get the pointer to the first item in a |
Implementation GuideVecOfSelfAsPtrWe can add a swift-bridge/crates/swift-bridge-build/src/generate_core/rust_vec.swift Lines 88 to 105 in d03f772
Then we can expose this behind Near here
Swift Integration TestWe can add a
Here's an example Vec Swift test swift-bridge/SwiftRustIntegrationTestRunner/SwiftRustIntegrationTestRunnerTests/VecTests.swift Lines 26 to 32 in b4c5d9b
Implementing
|
#[export_name = concat!("__swift_bridge__$Vec_", stringify!($ty), "$get")] | |
#[doc(hidden)] | |
pub extern "C" fn _get( | |
vec: *mut Vec<$ty>, | |
index: usize, | |
) -> crate::option::$option_ty { | |
let vec = unsafe { &*vec }; | |
if let Some(val) = vec.get(index) { | |
crate::option::$option_ty { | |
val: *val, | |
is_some: true, | |
} | |
} else { | |
crate::option::$option_ty { | |
val: $unused_none, | |
is_some: false, | |
} | |
} | |
} |
and here
swift-bridge/crates/swift-bridge-build/src/generate_core.rs
Lines 158 to 165 in fdca9fc
public static func vecOfSelfPop(vecPtr: UnsafeMutableRawPointer) -> Optional<Self> {{ | |
let val = __swift_bridge__$Vec_{rust_ty}$pop(vecPtr) | |
if val.is_some {{ | |
return val.val | |
}} else {{ | |
return nil | |
}} | |
}} |
Testing
Here's how to run the tests to confirm that the new tests pass:
cargo test --all && ./test-swift-rust-integration.sh
RustVec<T>.as_ptr() -> UnsafePointer<T>
method
Wow awesome. I would be up for giving this a shot. One thing I didn't get on the first read of your answer was how to deal with the |
By the way it looks like we already have swift-bridge/src/std_bridge/rust_vec.rs Lines 109 to 114 in 7c1daae
|
I am using protobuf to pass data back and forth between a cross-platform library and client apps on various platforms. I have successfully gotten my code to work without swift-bridge, but I thought I'd give it a go since it would be much easier to automatically generate the Swift Package, and potentially make my code a bit cleaner.
For protobuf, the only data that I pass around is a bucket of bytes. I suppose there are two options:
Vec<u8>
from swift as aRustVec<UInt8>
, but but then I don't know how to convert that into aData
in Swift for passing back to protobuf.For option 1, the generated Swift code appears to be wrong:
In my manual version, I called the function using
&UnsafeMutablePointer<UInt8>&
, notUnsafeMutablePointer<UnsafeMutablePointer<UInt8>>
.I'm pretty new to Swift, so I'm not sure what all the nuances of these things are, this is just what worked / what didn't work for me.
For reference, here is the working (non swift-bridge) call site corresponding to the same Rust signature as above:
(Edit: formatting)
The text was updated successfully, but these errors were encountered: