C# / .NET bindings for iceoryx2 - Zero-Copy Lock-Free IPC
Important
This repository is meant to be integrated into eclipse-iceoryx soon.
✅ Production-Ready C# Bindings!
- ✅ Cross-platform library loading (macOS tested, Linux/Windows ready)
- ✅ Complete P/Invoke FFI layer for all core APIs
- ✅ Memory-safe resource management with SafeHandle pattern
- ✅ High-level C# wrappers with builder pattern
- ✅ Publish-Subscribe API - Full implementation with type safety and zero-copy
- ✅ Event API - Complete notifier/listener implementation with blocking/timed waits
- ✅ Request-Response API - Complete client/server RPC with verified FFI signatures
- ✅ Complex Data Types - Full support for custom structs with sequential layout
- ✅ Async/Await Support - Modern async methods for all blocking operations with CancellationToken
- ✅ CI/CD - GitHub Actions workflow for multi-platform builds and NuGet packaging
- ✅ Tests passing on macOS
- ✅ Working examples for all major APIs (Pub/Sub, Event, RPC)
- ✅ Production-ready with proper memory management and error handling
⚠️ Requires native library:libiceoryx2_ffi_c.{so|dylib|dll}(included in git submodule)
This package provides C# and .NET bindings for iceoryx2, enabling zero-copy inter-process communication in .NET applications. The bindings use P/Invoke to call into the iceoryx2 C FFI layer and provide idiomatic C# APIs with full memory safety.
- 🚀 Zero-copy IPC - Share memory between processes without serialization
- 🔒 Type-safe - Full C# type system support with compile-time checks
- 🧹 Memory-safe - Automatic resource management via SafeHandle and IDisposable
- 🎯 Idiomatic C# - Builder pattern, Result types, LINQ-friendly APIs
- 🔧 Cross-platform - Works on Linux, macOS, and Windows
- 📦 Multiple patterns - Publish-Subscribe, Event, and Request-Response communication
- ⚡ Async/Await - Full async support with CancellationToken for modern C# applications
- 🔍 Service Discovery - Dynamically discover and monitor running services
- 🌐 Domain Isolation - Separate communication groups for multi-tenant deployments
Understanding these core concepts will help you use iceoryx2-csharp effectively:
Unlike traditional IPC mechanisms (sockets, pipes) that serialize and copy data, iceoryx2 uses shared memory for true zero-copy communication:
┌─────────────────────────────────────────────────────────────────┐
│ Shared Memory Region │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Data Payload │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↑ ↑ │
│ │ Direct Write │ Direct Read │
│ ┌─────┴──────┐ ┌─────┴──────┐ │
│ │ Publisher │ │ Subscriber │ │
│ │ (Process A)│ │ (Process B)│ │
│ └────────────┘ └────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Benefits:
- No serialization - Data is accessed directly in shared memory
- Constant-time transfer - Transfer time is independent of payload size
- Low latency - Microsecond-level communication
- High throughput - Limited only by memory bandwidth
iceoryx2 organizes communication through services. Each service has a unique name and supports one of three communication patterns:
| Pattern | Description | Use Case |
|---|---|---|
| Publish-Subscribe | One-to-many data distribution | Sensor data, telemetry, state broadcasts |
| Event | Lightweight notifications with event IDs | Wake-up signals, state changes, triggers |
| Request-Response | Client-server RPC | Commands, queries, configuration updates |
A Node represents your application's identity within iceoryx2. Nodes:
- Own and manage services
- Have unique names for identification
- Monitor other nodes (detect dead/unresponsive nodes)
- Are required to create any service
using var node = NodeBuilder.New()
.Name("my_application")
.Create()
.Unwrap();For zero-copy to work correctly, data types must have a defined memory layout:
using System.Runtime.InteropServices;
// ✅ CORRECT: Sequential layout ensures consistent memory representation
[StructLayout(LayoutKind.Sequential)]
public struct SensorData
{
public int SensorId;
public double Temperature;
public long Timestamp;
}
// ❌ WRONG: Default layout may differ across processes
public struct BadData
{
public int Value;
public string Name; // Reference types not supported!
}Requirements:
- Use
[StructLayout(LayoutKind.Sequential)]attribute - Only use unmanaged types (primitives, fixed arrays, nested sequential structs)
- Avoid reference types (strings, arrays, classes)
- For cross-language compatibility with Rust/C, this matches
#[repr(C)]
Domains provide isolated communication groups, preventing interference between unrelated applications:
┌─────────────────────────────────────────────────────────────────┐
│ Domain "production" │ Domain "development" │
│ ┌─────────┐ ┌─────────┐ │ ┌─────────┐ ┌─────────┐ │
│ │ App A │ │ App B │ │ │ App A' │ │ App B' │ │
│ └────┬────┘ └────┬────┘ │ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │ │
│ ┌────▼───────────▼────┐ │ ┌────▼───────────▼────┐ │
│ │ Shared Services │ │ │ Shared Services │ │
│ └─────────────────────┘ │ └─────────────────────┘ │
│ │ │
│ (Cannot see each other) │ │
└─────────────────────────────┴───────────────────────────────────┘
Use domains to:
- Run multiple instances of the same application
- Isolate test environments from production
- Separate different tenants in multi-tenant systems
dotnet add package Iceoryx2Or add to your .csproj:
<ItemGroup>
<PackageReference Include="Iceoryx2" Version="0.1.0" />
</ItemGroup>The NuGet package includes pre-built native libraries for macOS, Linux, and Windows.
Important
iceoryx2 is included as a git submodule and must be initialized and built before building the .NET project.
# Clone the repository with submodules
git clone --recursive https://github.com/eclipse-iceoryx/iceoryx2-csharp.git
cd iceoryx2-csharp
# Or if already cloned, initialize submodules
git submodule update --init --recursiveThe iceoryx2 C FFI library must be built first as the .NET project depends on it:
# From repository root
cd iceoryx2
cargo build --release --package iceoryx2-ffi-c
cd ..This creates the native library at:
- Linux:
iceoryx2/target/release/libiceoryx2_ffi_c.so - macOS:
iceoryx2/target/release/libiceoryx2_ffi_c.dylib - Windows:
iceoryx2/target/release/iceoryx2_ffi_c.dll
# From repository root
dotnet buildThe build automatically copies the native library from iceoryx2/target/release/
to the output directories.
dotnet test# Terminal 1 - Publisher
cd examples/PublishSubscribe
dotnet run -- publisher
# Terminal 2 - Subscriber
cd examples/PublishSubscribe
dotnet run -- subscriberYou should see the subscriber receiving incrementing counter values from the publisher!
- .NET 8.0 or .NET 9.0 SDK (Download)
- Rust toolchain (for building the iceoryx2 C FFI library) - Install via rustup
- C compiler and libclang (required for building iceoryx2):
- Linux:
sudo apt-get install clang libclang-dev - macOS:
brew install llvm(usually pre-installed with Xcode) - Windows: MSVC Build Tools (usually included with Visual Studio)
- Linux:
Note
The iceoryx2 project is included as a git submodule. You must initialize it before building.
# If you haven't cloned with --recursive
git submodule update --init --recursiveImportant
The iceoryx2 C FFI library must be built before the .NET project.
# From repository root
cd iceoryx2
cargo build --release --package iceoryx2-ffi-c
cd ..This creates the native library in iceoryx2/target/release/:
- Linux:
libiceoryx2_ffi_c.so - macOS:
libiceoryx2_ffi_c.dylib - Windows:
iceoryx2_ffi_c.dll
# From repository root
dotnet build --configuration ReleaseThe build process automatically:
- Copies the native library to all output directories
- Builds all projects (iceoryx2, iceoryx2.Reactive, tests, examples)
dotnet test --configuration ReleaseAll examples are built automatically with the solution. To run a specific example:
Publish-Subscribe Example:
# Terminal 1 - Run publisher
cd examples/PublishSubscribe
dotnet run -- publisher
# Terminal 2 - Run subscriber
cd examples/PublishSubscribe
dotnet run -- subscriberEvent Example:
# Terminal 1 - Run notifier
cd examples/Event
dotnet run -- notifier
# Terminal 2 - Run listener
cd examples/Event
dotnet run -- listenerA convenience build script is provided that handles all steps:
./build.shThis script:
- Builds the iceoryx2 C FFI library
- Generates C# bindings (optional)
- Builds the .NET solution
- Runs tests
- Builds examples
The C# bindings automatically detect and load the correct native library for your platform:
| Platform | Library Names (tried in order) |
|---|---|
| Linux | libiceoryx2_ffi_c.so, iceoryx2_ffi_c.so |
| macOS | libiceoryx2_ffi_c.dylib, iceoryx2_ffi_c.dylib |
| Windows | iceoryx2_ffi_c.dll, libiceoryx2_ffi_c.dll |
iceoryx2-csharp/
├── iceoryx2/ # Git submodule - iceoryx2 Rust implementation
├── src/
│ ├── Iceoryx2/ # Main C# library
│ │ ├── Native/ # C-bindings via P/Invoke
│ │ ├── SafeHandles/ # Memory-safe resource management
│ │ ├── Core/ # High-level API wrappers
│ │ ├── PublishSubscribe/ # Pub/Sub messaging pattern
│ │ ├── Event/ # Event-based communication
│ │ ├── RequestResponse/ # Request-Response (RPC) pattern
│ │ └── Types/ # Common types and utilities
│ └── Iceoryx2.Reactive/ # Reactive Extensions support
├── examples/ # C# examples
│ ├── PublishSubscribe/ # Pub/Sub example
│ ├── ComplexDataTypes/ # Complex struct example
│ ├── Event/ # Event API example
│ ├── RequestResponse/ # Request-Response RPC example
│ ├── AsyncPubSub/ # Async/await patterns example
│ ├── WaitSetMultiplexing/ # Event multiplexing with WaitSet
│ └── ServiceDiscovery/ # Service discovery and monitoring
├── tests/ # Unit tests
├── ARCHITECTURE.md # Architecture and design documentation
└── README.md
Detailed usage examples for different patterns (Publish-Subscribe, Event, Request-Response, etc.) can be found in examples/README.md.
For a deep dive into the architecture and design decisions, see ARCHITECTURE.md.
Note
To run the examples, you must specify the target framework:
dotnet run --framework net9.0
Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.
See ROADMAP.md for the current project roadmap and future plans.
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.