rust-diplomat / diplomat

Experimental Rust tool for generating FFI definitions allowing many other languages to call Rust code
https://rust-diplomat.github.io/book/
Other
476 stars 45 forks source link

dotnet: support mutable references to primitive and primitive-like (enums) types #134

Open CBenoit opened 2 years ago

CBenoit commented 2 years ago

The out parameter modifier can be used to support that.

:exclamation: Currently backend is just generating incorrect code (fortunately, it doesn't compile).

This would be nice to support alternate functions that does not throw exceptions when performance matters. For instance, Int32.Parse has a non-throwing counter part called Int32.TryParse.

struct Foo;

impl Foo {
  // C# wrapper will throw an exception on error
  pub fn parse(s: &str) -> Result<u32> { … }

  // In this version, an error code is returned instead
  #[diplomat_attr(not(dotnet), ignore)] // Useful only for backends relying on exceptions for errors
  pub fn try_parse(s: &str, result: &mut u32) -> bool {
    match Self::parse(s) {
      Ok(v) => {
        *result = v;
        true;
      }
      Err(_) => false,
    }
  }
}
Manishearth commented 2 years ago

I wonder if any of the backends handles this well: because on many of them you need conversion before mutation, and I'm wondering if it just makes more sense to ask people to write the APIs as taking in the primitive and spitting out a new one. (Perhaps expand the restriction on non-opaque structs to be that references can only contain opaque types/strings/slices, no primitives, and no mutation on strings/slices). Unsure though.

CBenoit commented 2 years ago

I'm wondering if it just makes more sense to ask people to write the APIs as taking in the primitive and spitting out a new one.

If we do that we can't support the use case mentioned above anymore, but it's not necessarily a big deal because it's always possible to manually extend generated C# classes with new functions and then provide a non-throwing version of Parse for instance. I would prefer to not write that manually, but not a blocker.

no mutation on strings/slices

However that restriction would be a bit problematic for me, because as mentioned in https://github.com/rust-diplomat/diplomat/pull/126, I have a use case largely depending on allowing this.

Manishearth commented 2 years ago

Yeah perhaps we should be lax about this, the main fear I have is that in some cases this requires a copy. If we can make this work with the JS backend I think it would be great.