.NET bindings
We distribute the .NET bindings as a NuGet package. Internally, the C API is called using P/Invoke. The bindings are .NET Standard 2.0 compatible and include platform-specific shared libraries that are automatically loaded by the .NET runtime.
Shared libraries for the following platforms are included in the Nuget package:
| Platform | Minimum OS |
|---|---|
| Windows x64 | Windows 10+ |
| Windows x86 | Windows 10+ |
| Linux x64 (GLIBC and MUSL variants) | kernel 3.2+, and glibc 2.17+ for GLIBC |
| Linux AArch64 (GLIBC and MUSL variants) | kernel 4.1+, and glibc 2.17+ for GLIBC |
| Linux ARMv6hf (GLIBC and MUSL variants) | kernel 3.2+, and glibc 2.17+ for GLIBC |
| MacOS x64 | MacOS 10.12+ |
| MacOS AArch64 | MacOS 11.0+ |
MacOS libraries are included in the package but are not officially supported. They are useful for developers using MacOS, but are not supported in production.
Supported .NET versions
The library targets .NET Standard 2.0, meaning it supports .NET Core 2.0+, .NET 5+ and .NET Framework 4.6.1+ (although at least 4.7.2 is recommended). A complete compatibility table is available on Microsoft website.
Version 2.0 will not support .NET Framework. It will target .NET Standard 2.1, which .NET Framework doesn't implement, so that the bindings' interfaces can have default methods. .NET Core 3.0 and later, and .NET 5 and later, will keep working.
On .NET Framework, you need to specify the platform you are targeting. The library currently does not support the AnyCPU platform. You need to
set the platform to either x64 or x86 in order for the MSBuild script to properly copy the DLL in the build directory.
For .NET Core and .NET 5+, the proper DLL is automatically loaded even with the AnyCPU platform.
Dependencies
The package depends on one open source package, which NuGet retrieves:
- System.Collections.Immutable - MIT - immutable collections
Mapping
C# is an object-oriented language that supports all the abstract patterns modeled in the code generator. Here's what you need to know.
Errors
C API errors are transformed into exceptions that contain the error enum.
Uncaught exceptions thrown in callbacks will terminate the program. Your code should always wrap callback logic with try/catch syntax if there's a chance that the callback will throw.
Iterators
The code generator transforms iterators into ICollection<T>. This means that the collections returned by callbacks may be used outside the callback. For example, you can send them to another thread for processing.
Structs
Native structs are mapped to C# classes. They have public member visibility, and the constructor ensures that all values without a reasonable default are initialized.
Each field has a With<FieldName> method that sets the field and returns the struct for chaining operations.
Classes
Classes are mapped to C# classes. They have a private pointer to the underlying native resource. There are two types of generated classes in C#:
- Generated classes that only have a private finalizer: These are automatically garbage collected, while native resources are deallocated in the class's finalize method. Most
are short-lived objects such as
CommandSet,Request, andAddressFilter. The exception isOutstation: an outstation created as a TCP or TLS client, or on a serial port or UDP socket, stops when it's garbage collected, so keep a reference to it for as long as it should run. - Generated classes that also provide a public
Shutdownmethod: These represent long-lived resources such asRuntime,MasterChannel, orOutstationServer. They map to an asynchronous Rust task executing on the Tokio runtime. TheShutdownmethod lets you precisely control when the resource/task will stop.MasterServerimplementsIDisposableand providesDisposeinstead.
Asynchronous methods
Asynchronous methods are transformed into methods that return Task<T>. C# Tasks are flexible and can be consumed in different ways:
- Synchronous applications can just call
Task.Resultto block for the value. An exception will be thrown if the task errors. - Asynchronous methods can
awaitthe completion of the task. - Synchronous methods may also use the various combinators like
Task.ContinueWithto process the result asynchronously.