uniffi-rs icon indicating copy to clipboard operation
uniffi-rs copied to clipboard

Trait interfaces can be wrapped multiple times

Open bendk opened this issue 5 months ago • 0 comments
trafficstars

When trait interfaces that have the with_foreign attribute are passed across the FFI, we always create a new wrapper layer. For example:

  • The trait interface is Rust is implemented in Rust
  • An instance of the trait interface is passed to Python
  • When Python code calls methods on the trait, behind the scenes we arrange for a Rust FFI call. All good so far
  • The Python code now passes this trait interface back to Rust.
  • Here's where the problems start. If the Rust code calls trait interface methods, it does so by making an FFI call to Python (via the vtable). The Python code that handles the FFI call, then goes back and makes an FFI call to Rust. We've just made a round-trip FFI call, for essentially no purpose.
  • If the trait interface was passed back again, then this issue would just compound and method invocations would require 3 trips across the FFI.

To fix this we need to:

  • Make it possible to know which side of the FFI a trait interface handle came from. For example, by using the lowest bit to signal Rust vs the foreign side. Maybe we should use 2-3 bits for this, so that we could support https://github.com/mozilla/uniffi-rs/issues/2295.
  • When passing a trait interface handle across the FFI, if we know it came from the other side then clone the handle and pass that back directly. Don't pass a handle to the callback interface implementation object that you constructed on your side of the FFI.
  • Take this into account when receiving a trait interface handle from across the FFI. For example, on the Rust side:
    • If the handle came from Rust, then re-construct the Arc<dyn Trait> using something like Arc::from_raw.
    • If the handle came from the foreign side, then keep the current behavior: create a new instance of our callback interface handler struct that implements Trait.

bendk avatar Jun 09 '25 19:06 bendk