Code Monkey home page Code Monkey logo

uniffi-bindgen-cs's Introduction

uniffi-bindgen-cs - UniFFI C# bindings generator

Generate UniFFI bindings for C#. uniffi-bindgen-cs lives as a separate project from uniffi-rs, as per uniffi-rs #1355.

How to install

Minimum Rust version required to install uniffi-bindgen-cs is 1.72. Newer Rust versions should also work fine.

cargo install uniffi-bindgen-cs --git https://github.com/NordSecurity/uniffi-bindgen-cs --tag v0.8.0+v0.25.0

How to generate bindings

uniffi-bindgen-cs path/to/definitions.udl

Generates bindings file path/to/definitions.cs

How to integrate bindings

To integrate the bindings into your projects, simply add the generated bindings file to your project. There are a few requirements depending on your target framework version.

  • .NET core 6.0 or higher

    <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
        <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    </PropertyGroup>
  • .NET framework 4.8

    <PropertyGroup>
        <TargetFramework>net48</TargetFramework>
        <LangVersion>10.0</LangVersion>
        <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
        <PackageReference Include="IsExternalInit" Version="1.0.3"/>
        <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
    </PropertyGroup>

Unsupported features

The following uniffi features are unsupported.

  • External types #40

  • Async functions #41

Known Limitations

The following valid Rust type definitions fail to be converted properly, but a simple work-around is given:

  • Enum variants having the same name as their member type #60

Configuration options

It's possible to configure some settings by passing --config argument to the generator.

uniffi-bindgen-cs path/to/definitions.udl --config path/to/uniffi.toml

Versioning

uniffi-bindgen-cs is versioned separately from uniffi-rs. UniFFI follows the SemVer rules from the Cargo Book which states "Versions are considered compatible if their left-most non-zero major/minor/patch component is the same". A breaking change is any modification to the C# bindings that demands the consumer of the bindings to make corresponding changes to their code to ensure that the bindings continue to function properly. uniffi-bindgen-cs is young, and it's unclear how stable the generated bindings are going to be between versions. For this reason, major version is currently 0, and most changes are probably going to bump minor version.

To ensure consistent feature set across external binding generators, uniffi-bindgen-cs targets a specific uniffi-rs version. A consumer using Go bindings (in uniffi-bindgen-go) and C# bindings (in uniffi-bindgen-cs) expects the same features to be available across multiple bindings generators. This means that the consumer should choose external binding generator versions such that each generator targets the same uniffi-rs version.

To simplify this choice uniffi-bindgen-cs and uniffi-bindgen-go use tag naming convention as follows: vX.Y.Z+vA.B.C, where X.Y.Z is the version of the generator itself, and A.B.C is the version of uniffi-rs it is based on.

The table shows uniffi-rs version history for tags that were published before tag naming convention described above was introduced.

uniffi-bindgen-cs version uniffi-rs version
v0.6.0 v0.25.0
v0.5.0 v0.24.0
v0.3.0 (DONT USE, UNFINISHED) 3142151e v0.24.0?
v0.2.0 v0.23.0
v0.1.0 v0.20.0

Documentation

More documentation is available in docs directory.

Contributing

For contribution guidelines, read CONTRIBUTING.md.

uniffi-bindgen-cs's People

Contributors

arg0d avatar ernestask avatar itrumper avatar jjanowsk avatar meenzen avatar roeierez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

uniffi-bindgen-cs's Issues

External types are not supported

External types are not supported right now, because C# has limitations regarding custom types. Custom types are implemented as C# type aliases with using directive using A = B;. The using directive is file local, and the type alias is not visible outside the file its defined in. So, trying to use external types with custom types results in broken code. It might be possible to external types referencing custom types, but we haven't had the time to explore this yet. Using library mode in uniffi 0.24, it might be possible to dereference external types across UDL boundary, and emit the underlying type directly without needing to reference type alias from another C# file.

Supporting external types without referencing custom types should be possible, but some kind of warning should be implemented to warn the users of this issue. Also, upstream tests can't be used, because the tests use external types to reference custom types. Supporting external types is not a priority for us right now, but contributions are welcome.

Uniffi default values may cause compiler error `CS1737` in generated bindings

Original struct:

#[derive(uniffi::Record)]
pub struct CreateRoomParameters {
    pub name: Option<String>,
    #[uniffi(default = None)]
    pub topic: Option<String>,
    pub is_encrypted: bool,
    #[uniffi(default = false)]
    pub is_direct: bool,
    pub visibility: RoomVisibility,
    pub preset: RoomPreset,
    #[uniffi(default = None)]
    pub invite: Option<Vec<String>>,
    #[uniffi(default = None)]
    pub avatar: Option<String>,
}

Generated bindings:

public record CreateRoomParameters (
    String? @name, 
    String? @topic = null, 
    bool @isEncrypted, 
    bool @isDirect = false, 
    RoomVisibility @visibility, 
    RoomPreset @preset, 
    List<String>? @invite = null, 
    String? @avatar = null
) {
}

This causes a CS1737 compiler error:

error CS1737: Optional parameters must appear after all required parameters

Version: v0.6.0+v0.25.0

Generated code from Enum in Rust has errors

Hello, and thank you very much for this crate! It is a big help for my project.

I have the following Rust code:

#[derive(uniffi::Enum)]
pub enum Shape {
    Rectangle { s: Rectangle },
    Ellipse { s: Ellipse },
}

#[derive(uniffi::Record)]
pub struct Rectangle {
    width: f64,
    height: f64,
}

#[derive(uniffi::Record)]
pub struct Ellipse {
    x_radius: f64,
    y_radius: f64,
}

which generates the following C# code when using --library mode:

public record Shape {
    
    public record Rectangle (
        Rectangle @s
    ) : Shape {}
    
    public record Ellipse (
        Ellipse @s
    ) : Shape {}

}

The C# Rectangle and Ellipse records both contain the error: "The primary constructor conflicts with the synthesized copy constructor." Which is documented by Microsoft.

There is also the following generated code:

class FfiConverterTypeShape : FfiConverterRustBuffer<Shape>{
    public static FfiConverterRustBuffer<Shape> INSTANCE = new FfiConverterTypeShape();

    public override Shape Read(BigEndianStream stream) {
        var value = stream.ReadInt();
        switch (value) {
            case 1:
                return new Shape.Rectangle(
                    FfiConverterTypeRectangle.INSTANCE.Read(stream)
                );
            case 2:
                return new Shape.Ellipse(
                    FfiConverterTypeEllipse.INSTANCE.Read(stream)
                );
            default:
                throw new InternalException(String.Format("invalid enum value '{0}' in FfiConverterTypeShape.Read()", value));
        }
    }

    public override int AllocationSize(Shape value) {
        switch (value) {
            case Shape.Rectangle variant_value:
                return 4
                    + FfiConverterTypeRectangle.INSTANCE.AllocationSize(variant_value.@s);
            case Shape.Ellipse variant_value:
                return 4
                    + FfiConverterTypeEllipse.INSTANCE.AllocationSize(variant_value.@s);
            default:
                throw new InternalException(String.Format("invalid enum value '{0}' in FfiConverterTypeShape.AllocationSize()", value));
        }
    }

    public override void Write(Shape value, BigEndianStream stream) {
        switch (value) {
            case Shape.Rectangle variant_value:
                stream.WriteInt(1);
                FfiConverterTypeRectangle.INSTANCE.Write(variant_value.@s, stream);
                break;
            case Shape.Ellipse variant_value:
                stream.WriteInt(2);
                FfiConverterTypeEllipse.INSTANCE.Write(variant_value.@s, stream);
                break;
            default:
                throw new InternalException(String.Format("invalid enum value '{0}' in FfiConverterTypeShape.Write()", value));
        }
    }
}

which has the error "Cannot convert from 'uniffi.uniffi_lib.Rectangle' to 'uniffi.uniffi_lib.Shape.Rectangle" for all cases. The same in reverse conversion too. Have you seen this error before? Do you have suggestions to help remedy this issue? I have not seen any limitations on support for Enums in this crate, just external types.

Thank you!

Consider using enum error code instead of nested exception types

An enum error type in UDL produces a C# exception with a nested derived exception type for each enum value.
For example:

internal class LightWalletException: UniffiException {
    LightWalletException(string message): base(message) {}

    // Each variant is a nested class
    // Flat enums carries a string error message, so no special implementation is necessary.
    
    public class InvalidUri: LightWalletException {
        public InvalidUri(string message): base(message) {}
    }
    
    public class InvalidHandle: LightWalletException {
        public InvalidHandle(string message): base(message) {}
    }
    
    public class Other: LightWalletException {
        public Other(string message): base(message) {}
    } 
}

But these exception types don't hold any unique properties. Why not nest this inside the exception instead?

	public enum ErrorCode
	{
		Other,
		InvalidUri,
		InvalidHandle,
	}
	public required ErrorCode Code { get; init; }

It results in less metadata. And in .NET in general, very finely grained exception types are discouraged. The enum approach still allows exception filters to catch specific cases. For example:

try {
    callIntoInterop();
} catch (LightWalletException ex) when (ex.Code == LightWalletException.ErrorCode.InvalidUri) {
  // handle invalid uri
}

This is all assuming that UDL doesn't support carrying distinct error enums data across the interop boundary. If different error enum values can actually carry distinct fields in UDL (as they can in rust) then C# should probably retain a distinct exception type for each one.

Option to generate internal APIs

The generated .cs file seems to include mostly internal types. But the class that contains the exported functions themselves is public. I don't want to expose these bare metal functions to folks who reference my assembly.
Can you add an option to emit all internal types?

Confusing cargo output when installing `v0.5.0+v0.24.0`

When running this command:

cargo install uniffi-bindgen-cs --git https://github.com/NordSecurity/uniffi-bindgen-cs.git --tag v0.5.0+v0.24.0

Cargo outputs:

Installed package `uniffi-bindgen-cs v0.2.4+v0.23.0 (https://github.com/NordSecurity/uniffi-bindgen-cs.git?tag=v0.5.0+v0.24.0#deff9263)` (executable `uniffi-bindgen-cs`)

It looks like the version in bindgen/Cargo.toml wasn't bumped before tagging the release.

`bytes` typedef does not compile

UDL

[Custom]
typedef bytes SomeType

Generated C#

using SomeType = bytes[];

Error

C:\workspace\uniffi-bindgen-cs\dotnet-tests\UniffiCS\gen\custom_types_builtin.cs(19,15): error CS8936: Feature 'using type alias' is not available in C# 10.0. Please use language version 12.0 or greater. [C:\workspace\uniffi-bindgen-cs\dotnet-tests\UniffiCS\UniffiCS.csproj::TargetFramework=net48]

Test diff repro:

diff --git a/fixtures/custom-types-builtin/src/custom_types_builtin.udl b/fixtures/custom-types-builtin/src/custom_types_builtin.udl
index c71fb4f..24170e0 100644
--- a/fixtures/custom-types-builtin/src/custom_types_builtin.udl
+++ b/fixtures/custom-types-builtin/src/custom_types_builtin.udl
@@ -12,6 +12,9 @@ typedef string MyString;
 [Custom]
 typedef sequence<string> Array;

+[Custom]
+typedef bytes Bytes;
+
 [Custom]
 typedef record<string, string> Table;

@@ -51,6 +54,7 @@ typedef double Double;
 dictionary CustomTypesBuiltin {
     MyString string;
     Array array;
+    Bytes bytes;
     Table table;
     Boolean boolean;
     Int8 int8;
diff --git a/fixtures/custom-types-builtin/src/lib.rs b/fixtures/custom-types-builtin/src/lib.rs
index 9352f02..56de1ba 100644
--- a/fixtures/custom-types-builtin/src/lib.rs
+++ b/fixtures/custom-types-builtin/src/lib.rs
@@ -23,6 +23,7 @@ macro_rules! define_custom_builtin_type {

 define_custom_builtin_type!(MyString, String);
 define_custom_builtin_type!(Array, Vec<String>);
+define_custom_builtin_type!(Bytes, Vec<u8>);
 define_custom_builtin_type!(Table, HashMap<String, String>);
 define_custom_builtin_type!(Boolean, bool);
 define_custom_builtin_type!(Int8, i8);
@@ -39,6 +40,7 @@ define_custom_builtin_type!(Double, f64);
 pub struct CustomTypesBuiltin {
     string: MyString,
     array: Array,
+    bytes: Bytes,
     table: Table,
     boolean: Boolean,
     int8: Int8,
@@ -57,6 +59,7 @@ pub fn get_custom_types_builtin() -> CustomTypesBuiltin {
     return CustomTypesBuiltin {
         string: MyString("Hello, world!".to_string()),
         array: Array(vec!["Hello, world!".to_string()]),
+        bytes: Bytes(vec![0x13, 0x37]),
         table: Table(HashMap::from([("hello".to_string(), "world".to_string())])),
         boolean: Boolean(true),
         int8: Int8(i8::MAX),

Error type named `Error` emits invalid code

Error is translated into Exception, and causes ambiguous type references between System.Exception and Exception.

/mounted_workdir/dotnet-tests/UniffiCS/gen/stringify.cs(215,16): error CS0146: Circular base type dependency involving 'Exception' and 'UniffiException' [/mounted_workdir/dotnet-tests/UniffiCS/UniffiCS.csproj]
/mounted_workdir/dotnet-tests/UniffiCS/gen/stringify.cs(274,7): error CS0311: The type 'uniffi.stringify.UniffiException' cannot be used as type parameter 'E' in the generic type or method 'CallStatusErrorHandler<E>'. There is no implicit reference conversion from 'uniffi.stringify.UniffiException' to 'uniffi.stringify.Exception'. [/mounted_workdir/dotnet-tests/UniffiCS/UniffiCS.csproj]
/mounted_workdir/dotnet-tests/UniffiCS/gen/stringify.cs(1553,16): error CS0146: Circular base type dependency involving 'UniffiException' and 'Exception' [/mounted_workdir/dotnet-tests/UniffiCS/UniffiCS.csproj]
/mounted_workdir/dotnet-tests/UniffiCS/gen/stringify.cs(297,35): error CS0311: The type 'E' cannot be used as type parameter 'E' in the generic type or method 'CallStatusErrorHandler<E>'. There is no implicit reference conversion from 'E' to 'uniffi.stringify.Exception'. [/mounted_workdir/dotnet-tests/UniffiCS/UniffiCS.csproj]
/mounted_workdir/dotnet-tests/UniffiCS/gen/stringify.cs(334,35): error CS0311: The type 'E' cannot be used as type parameter 'E' in the generic type or method 'CallStatusErrorHandler<E>'. There is no implicit reference conversion from 'E' to 'uniffi.stringify.Exception'. [/mounted_workdir/dotnet-tests/UniffiCS/UniffiCS.csproj]
/mounted_workdir/dotnet-tests/UniffiCS/gen/stringify.cs(215,16): error CS0146: Circular base type dependency involving 'Exception' and 'UniffiException' [/mounted_workdir/dotnet-tests/UniffiCS/UniffiCS.csproj]
/mounted_workdir/dotnet-tests/UniffiCS/gen/stringify.cs(274,7): error CS0311: The type 'uniffi.stringify.UniffiException' cannot be used as type parameter 'E' in the generic type or method 'CallStatusErrorHandler<E>'. There is no implicit reference conversion from 'uniffi.stringify.UniffiException' to 'uniffi.stringify.Exception'. [/mounted_workdir/dotnet-tests/UniffiCS/UniffiCS.csproj]
/mounted_workdir/dotnet-tests/UniffiCS/gen/stringify.cs(1553,16): error CS0146: Circular base type dependency involving 'UniffiException' and 'Exception' [/mounted_workdir/dotnet-tests/UniffiCS/UniffiCS.csproj]
/mounted_workdir/dotnet-tests/UniffiCS/gen/stringify.cs(297,35): error CS0311: The type 'E' cannot be used as type parameter 'E' in the generic type or method 'CallStatusErrorHandler<E>'. There is no implicit reference conversion from 'E' to 'uniffi.stringify.Exception'. [/mounted_workdir/dotnet-tests/UniffiCS/UniffiCS.csproj]
/mounted_workdir/dotnet-tests/UniffiCS/gen/stringify.cs(334,35): error CS0311: The type 'E' cannot be used as type parameter 'E' in the generic type or method 'CallStatusErrorHandler<E>'. There is no implicit reference conversion from 'E' to 'uniffi.stringify.Exception'. [/mounted_workdir/dotnet-tests/UniffiCS/UniffiCS.csproj]
$ git diff
diff --git a/Cargo.lock b/Cargo.lock
index 4c8e079..385723a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1241,6 +1241,7 @@ name = "uniffi-cs-stringify"
 version = "1.0.0"
 dependencies = [
  "paste",
+ "thiserror",
  "uniffi",
  "uniffi_macros",
 ]
diff --git a/fixtures/stringify/Cargo.toml b/fixtures/stringify/Cargo.toml
index fd88f7f..d7e6f43 100644
--- a/fixtures/stringify/Cargo.toml
+++ b/fixtures/stringify/Cargo.toml
@@ -12,6 +12,7 @@ name = "stringify"
 paste = "1.0"
 uniffi = {path = "../../3rd-party/uniffi-rs/uniffi", features=["build"]}
 uniffi_macros = {path = "../../3rd-party/uniffi-rs/uniffi_macros"}
+thiserror = "1.0"
 
 [build-dependencies]
 uniffi = {path = "../../3rd-party/uniffi-rs/uniffi", features=["bindgen-tests"]}
diff --git a/fixtures/stringify/src/lib.rs b/fixtures/stringify/src/lib.rs
index fa73ca4..09642a9 100644
--- a/fixtures/stringify/src/lib.rs
+++ b/fixtures/stringify/src/lib.rs
@@ -4,6 +4,10 @@
 
 use paste::paste;
 
+#[derive(Debug, thiserror::Error, uniffi::Error)]
+pub enum Error {
+}
+
 uniffi::setup_scaffolding!();
 
 macro_rules! define_parse_function {

Empty struct causes errors in generated code

Given the following Rust struct:

#[derive(Record)]
struct Test {}

the generated C# code is:

public record Test (
) {
}

class FfiConverterTypeTest: FfiConverterRustBuffer<Test> {
    public static FfiConverterTypeTest INSTANCE = new FfiConverterTypeTest();

    public override Test Read(BigEndianStream stream) {
        return new Test(
        );
    }

    public override int AllocationSize(Test value) {
        return;
    }

    public override void Write(Test value, BigEndianStream stream) {
    }
}

which contains the error "CS0126 An object of a type convertible to 'int' is required". This comes from the empty return in the AllocationSize method. Adding a return value of 0 is I think the correct solution, as that is what Rust allocates for this struct. Thoughts?

Emit partial types

For the data types, please emit them with the partial keyword so we can add members to them outside the generated code.

Name collisions with supporting types

There are a bunch of supporting/internal types that can cause name collisions with consumer's namespace. These aren't very generic and not used very often unlike some other types, i.e. File, Stream, etc.., but thinking long term this could for sure create problems for someone. I wonder maybe its possible to neatly wrap all these supporting types into their own namespace.

AllocationException
BigEndianStream
CallStatusErrorHandler
ConcurrentHandleMap
FfiConverter*
FFIObject
FFIObjectUtil
FFISafeHandle
ForeignBytes
ForeignCallback
InternalException
InvalidEnumException
NullCallStatusErrorHandler
PanicException
RustBuffer
RustCallStatus
StreamUnderflowException
UndeclaredErrorException
UniffiException

Async functions are not supported

I have tried to implement async functions for 0.24, but ran into some issues.

  1. The performance is inadequate. Trying to await 1000 functions that only sleep for 100ms and return, takes around 1 second. This equates to around 1ms per async function call. I'm completely dumbfounded why this happens. I don't have time right now to try and profile this.

  2. Returning objects from functions is not working in some cases. The C# marshaller complains that SafeHandle cannot be marshalled. This happens when future callback is being invoked. A solution could be to rework the code to use IntPtr instead of SafeHandle.

With uniffi 0.25 just around the corner, it seems like async functions have had a significant rework. I'm hoping that the changes in 0.25 might automatically solve at least one of these issues. As this is not a priority for us right now, I'm postponing async functions for later.

Ensure type names are generated uniformly independent of capitalization

I have a type declared as interface ASDFObject in my UDL file, which works without issue in Swift/Kotlin/Python.

When trying to generate CS bindings, the output file however includes

public class AsdfObjectSafeHandle: FFISafeHandle {

while the constructors then are defined as

public static extern ASDFObjectSafeHandle ... 

... which of course doesn't compile. If I switch the Rust/UDL type name to be AsdfObject everything seems to be generated uniformly, which I however would like to avoid.

Emit "// <auto-generated/>" at top of file

The generated file produces a lot of warnings from StyleCop and other analyzers. Fixing all these is unreasonable. But all generated files should include a particular header that turns these off:

// <auto-generated/>

This one line at the very top of the file addresses almost everything.
The only exception to this are the CS1591 and RS0016 warnings that #23 should address.

`Error: Unexpected metadata type code` when using the library mode

I can't get the library mode to work for the matrix-rust-sdk, somehow the embedded metadata is not being read correctly. The upstream uniffi-bindgen tool does not have the same issue.

> uniffi-bindgen-cs --library ../../target/debug/libmatrix_sdk_ffi.so --out-dir out                             
Error: Unexpected metadata type code: 82
> uniffi-bindgen-cs --library ../../target/release/libmatrix_sdk_ffi.so --out-dir out
Error: Unexpected metadata type code: 37

rel: https://github.com/mozilla/uniffi-rs/blob/main/uniffi_meta/src/reader.rs#L61

Version: v0.5.1+v0.24.0

Formatting generated c# files

While reading through the source code I noticed the following comment:

// TODO: find a way to easily format standalone C# files
// https://github.com/dotnet/format

I highly recommend taking a look at the tool Csharpier, it is a lot faster and more reliable than dotnet-format and can format single files:

dotnet csharpier foo.cs

Note that files containg a <auto-generated/> header #25 will not be formatted, so the formatting stage must occur before writing the header.

junk remaining in buffer after lifting, something is very wrong!!

Oh dear. I saw this today:

uniffi.LightWallet.InternalException
  HResult=0x80131500
  Message=junk remaining in buffer after lifting, something is very wrong!!
  Source=Nerdbank.Zcash
  StackTrace:
   at uniffi.LightWallet.FfiConverter`2.LiftFromRustBuffer(RustBuffer rbuf) in C:\git\Nerdbank.Cryptocurrencies\src\Nerdbank.Zcash\RustBindings\LightWallet.cs:line 165

What kind of information would help you diagnose this? I've been able to repro it twice in a row (out of two attempts).

Add support for `bytes` UDL type

Going off the documented built-in types, I see only a few candidates for passing a byte array around. I tried bytes, but this C# generator doesn't support that. I then tried sequence<u8> but the C# binding for that was List<byte> which is not what I want to have to pass in.

Ideally, I'd like to pass in ReadOnlySpan<byte> or Span<byte> (based on whether I expect the rust code to write to the buffer) and avoid any memory copying.

`bytes` type produces incorrect code in some situations

bytes type produces incorrect code in the following situations:

  • u8 is not referenced anywhere else in the definition file. This causes undefined symbol FfiConverterUint8.
  • Vec<u8> is referenced somewhere in the definition file. This causes duplicate symbol definition for FfiConverterSequenceUint8.

Does this tool have an equivalent flag to `--lib-file` from the UniFFI Bindgen CLI?

Hi, I'm currently using the new experimental macro features from the UniFFI toolkit instead of writing out a .udl file by hand. In this approach the information needed to generate the bindings is all stored in the static or dynamic library and we need to specify a static or dynamic library through the --lib-file flag on the UniFFI bindgen tool during generation time.

Looking at this tool, I do not see support for a --lib-file flag or an equivalent. Does the CSharp generator currently support this? If not, does the team plan on adding support for this in the future?

Timeline for UniFFI v0.26 tag release

My crate uses features that were implemented in v0.26 of uniffi. There is not a current tag for that version which is compatible with this tool. Do you have a timeline for when that next release may happen? Thank you!

Perhaps custom types should use C# Record with one positional argument

In uniffi documentation, it uses the following example for custom type:

pub struct Handle(i64);

Which, in Rust, is a new type.

On the generate C# code, alias is used. This does not create a new type. This type may not be named outside of the module. Perhaps custom types should use C# Record with one positional argument that matches the UDL typedef.

xml doc comments are not valid on record parameters

Given a UDL that includes this:

dictionary Transaction {
	u32 account_id;
	bytes txid;
	timestamp? block_time;
	u32? mined_height;
	boolean expired_unmined;
	i64 account_balance_delta;
	u64? fee;
	/// Notes that are sent by this transaction (and do not appear in `change`).
	sequence<TransactionNote> outgoing;
	/// Notes that are received by this transaction (and do not appear in `change`).
	sequence<TransactionNote> incoming;
	/// Notes that are sent and received by the same account and bear other signs of being implicit change.
	sequence<TransactionNote> change;
};

uniffi-bindgen-cs generates this:

internal record Transaction(
	uint @accountId,
	byte[] @txid,
	DateTime? @blockTime,
	uint? @minedHeight,
	bool @expiredUnmined,
	long @accountBalanceDelta,
	ulong? @fee,
	/// <summary>
	/// Notes that are sent by this transaction (and do not appear in `change`).
	/// </summary>
	List<TransactionNote> @outgoing,
	/// <summary>
	/// Notes that are received by this transaction (and do not appear in `change`).
	/// </summary>
	List<TransactionNote> @incoming,
	/// <summary>
	/// Notes that are sent and received by the same account and bear other signs of being implicit change.
	/// </summary>
	List<TransactionNote> @change
) { }

But this produces CS1587 warnings because xml doc comments are not valid on record primary constructor parameters. They must instead be placed on the record itself, like this:

/// <param name="outgoing">Notes that are sent by this transaction (and do not appear in `change`).</param>
/// <param name="incoming">Notes that are received by this transaction (and do not appear in `change`).</param>
/// <param name="change">Notes that are sent and received by the same account and bear other signs of being implicit change.</param>
internal record Transaction(
	uint @accountId,
	byte[] @txid,
	DateTime? @blockTime,
	uint? @minedHeight,
	bool @expiredUnmined,
	long @accountBalanceDelta,
	ulong? @fee,
	List<TransactionNote> @outgoing,
	List<TransactionNote> @incoming,
	List<TransactionNote> @change
) { }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.