### Run Example with Target Framework Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/README.md When running examples, it is necessary to specify the target framework using the --framework argument. ```bash dotnet run --framework net9.0 ``` -------------------------------- ### Run Task Communication Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/TaskCommunication/README.md Navigate to the example directory and run the .NET application. Press Ctrl+C for graceful shutdown. ```bash cd examples/TaskCommunication dotnet run ``` -------------------------------- ### Run Publish-Subscribe Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/README.md Execute the publish-subscribe example by running the publisher in one terminal and the subscriber in another. ```bash # Terminal 1 - Publisher cd examples/PublishSubscribe dotnet run -- publisher # Terminal 2 - Subscriber cd examples/PublishSubscribe dotnet run -- subscriber ``` -------------------------------- ### Run Blackboard Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/README.md Demonstrates the Blackboard key-value store pattern. Run the creator in one terminal and the opener in another. Navigate to the example directory first. ```bash # Terminal 1 - Run creator cd examples/Blackboard dotnet run -- creator ``` ```bash # Terminal 2 - Run opener cd examples/Blackboard dotnet run -- opener ``` -------------------------------- ### Run Publish-Subscribe Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/README.md Demonstrates the Publish-Subscribe pattern. Run the publisher in one terminal and the subscriber in another. Navigate to the example directory first. ```bash # Terminal 1 - Run publisher cd examples/PublishSubscribe dotnet run -- publisher ``` ```bash # Terminal 2 - Run subscriber cd examples/PublishSubscribe dotnet run -- subscriber ``` -------------------------------- ### Start the Creator Process Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/Blackboard/README.md Run this command in a terminal to start the process that creates and updates the blackboard service. ```bash dotnet run -- creator ``` -------------------------------- ### Run WaitSet Multiplexing Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Initiates the WaitSetMultiplexing example, setting up a wait on multiple services. This demonstrates efficient multiplexing of events from various sources. ```bash # Terminal 1 - Wait on multiple services cd examples/WaitSetMultiplexing dotnet run --framework net9.0 wait service1 service2 ``` -------------------------------- ### Run Async Publisher Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Starts the asynchronous publisher for the AsyncPubSub example. Ensure the publisher is running before starting subscribers. ```bash # Terminal 1 - Async publisher cd examples/AsyncPubSub dotnet run --framework net9.0 publisher ``` -------------------------------- ### Build Reactive Event Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ReactiveEventExample/README.md Builds the ReactiveEventExample project. Navigate to the example's directory and run the dotnet build command. ```bash cd iceoryx2-csharp/examples/ReactiveEventExample dotnet build ``` -------------------------------- ### Run Service Discovery Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Executes the ServiceDiscovery example to list and inspect running services. Ensure other iceoryx services are active before running this to observe dynamic discovery. ```bash # First, start some services in another terminal (e.g., PublishSubscribe example) # Then run the discovery example: cd examples/ServiceDiscovery dotnet run --framework net9.0 ``` -------------------------------- ### Start the Opener Process Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/Blackboard/README.md Run this command in a terminal to start a process that connects to and reads from the blackboard service. ```bash dotnet run -- opener ``` -------------------------------- ### Build Request-Response Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/RequestResponse/README.md Builds the request-response example for iceoryx2 in C#. Ensure .NET 8.0 SDK or later and the iceoryx2 C FFI library are built. ```sh cd iceoryx2-csharp/examples/RequestResponse dotnet build ``` -------------------------------- ### Run Event Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/README.md Demonstrates the Event communication pattern. Run the notifier in one terminal and the listener in another. Navigate to the example directory first. ```bash # Terminal 1 - Run notifier cd examples/Event dotnet run -- notifier ``` ```bash # Terminal 2 - Run listener cd examples/Event dotnet run -- listener ``` -------------------------------- ### Publisher Example Output Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ComplexDataTypes/README.md Sample output from the iceoryx2 C# publisher demonstrating sending TransmissionData. ```text [Publisher] Starting with type: TransmissionData [Publisher] Type size: 16 bytes [Publisher] Service: ComplexTypes/Transmission Publisher created successfully. Press Ctrl+C to stop. Sending: TransmissionData { x: 0, y: 0, funky: 0.00 } Sending: TransmissionData { x: 1, y: 3, funky: 812.12 } Sending: TransmissionData { x: 2, y: 6, funky: 1624.24 } ... ``` -------------------------------- ### Run Waiter with .NET 9.0 Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/WaitSetMultiplexing/README.md Start the waiter program monitoring 'service_a' and 'service_b' using .NET 9.0. ```bash dotnet run --framework net9.0 -- wait service_a service_b ``` -------------------------------- ### Run the Publisher Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/AsyncPubSub/README.md Starts the publisher application which sends incrementing counter values every second. ```bash dotnet run publisher ``` -------------------------------- ### Run Waiter with .NET 8.0 Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/WaitSetMultiplexing/README.md Start the waiter program monitoring 'service_a' and 'service_b' using .NET 8.0. ```bash dotnet run --framework net8.0 -- wait service_a service_b ``` -------------------------------- ### Subscriber Example Output Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ComplexDataTypes/README.md Sample output from the iceoryx2 C# subscriber demonstrating receiving TransmissionData. ```text [Subscriber] Starting with type: TransmissionData [Subscriber] Type size: 16 bytes [Subscriber] Service: ComplexTypes/Transmission Subscriber ready. Waiting for samples... Press Ctrl+C to stop. Received: TransmissionData { x: 0, y: 0, funky: 0.00 } Received: TransmissionData { x: 1, y: 3, funky: 812.12 } Received: TransmissionData { x: 2, y: 6, funky: 1624.24 } ... ``` -------------------------------- ### Publish-Subscribe Pattern Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Demonstrates creating a node, opening a service, and sending/receiving data using the publish-subscribe pattern. Ensure proper error handling for all operations. ```csharp using Iceoryx2; // Create a node var nodeResult = NodeBuilder.New() .Name("my_node") .Create(); if (!nodeResult.IsOk) { Console.WriteLine($"Failed to create node: {nodeResult}"); return; } using var node = nodeResult.Unwrap(); // Open or create a service for pub/sub var serviceResult = node.ServiceBuilder() .PublishSubscribe() .Open("MyService"); if (!serviceResult.IsOk) { Console.WriteLine($"Failed to open service: {serviceResult}"); return; } using var service = serviceResult.Unwrap(); // Publisher example var publisherResult = service.CreatePublisher(); if (!publisherResult.IsOk) { Console.WriteLine($"Failed to create publisher: {publisherResult}"); return; } using var publisher = publisherResult.Unwrap(); var sampleResult = publisher.Loan(); if (!sampleResult.IsOk) { Console.WriteLine($"Failed to loan sample: {sampleResult}"); return; } using var sample = sampleResult.Unwrap(); sample.Payload = 42; var sendResult = sample.Send(); if (!sendResult.IsOk) { Console.WriteLine($"Failed to send: {sendResult}"); } // Subscriber example var subscriberResult = service.CreateSubscriber(); if (!subscriberResult.IsOk) { Console.WriteLine($"Failed to create subscriber: {subscriberResult}"); return; } using var subscriber = subscriberResult.Unwrap(); var receiveResult = subscriber.Receive(); if (!receiveResult.IsOk) { Console.WriteLine($"Failed to receive: {receiveResult}"); return; } var receivedSample = receiveResult.Unwrap(); if (receivedSample != null) { Console.WriteLine($"Received: {receivedSample.Payload}"); } ``` -------------------------------- ### Run Other AsyncPubSub Modes Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Demonstrates alternative modes for the AsyncPubSub example, including blocking and multi-subscriber scenarios. These showcase different communication and processing strategies. ```bash # Or try other modes: blocking, multi dotnet run --framework net9.0 blocking dotnet run --framework net9.0 multi ``` -------------------------------- ### Run the Subscriber (with timeout) Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/AsyncPubSub/README.md Starts a subscriber application that waits up to 5 seconds for each sample. ```bash # In another terminal dotnet run subscriber ``` -------------------------------- ### Run iceoryx2 C# Publisher with TransmissionData Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ComplexDataTypes/README.md Command to run the publisher example using the TransmissionData struct. ```bash cd examples/ComplexDataTypes dotnet run --framework net9.0 -- publisher TransmissionData ``` -------------------------------- ### Run iceoryx2 C# Publisher with Other Data Types Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ComplexDataTypes/README.md Commands to run the publisher example with different data types like SensorData or PointData. ```bash dotnet run --framework net9.0 -- publisher SensorData ``` ```bash dotnet run --framework net9.0 -- publisher PointData ``` -------------------------------- ### Create and Use Publisher in C# Source: https://context7.com/eclipse-iceoryx/iceoryx2-csharp/llms.txt Demonstrates creating a Publisher and sending data using zero-copy loan, mutable reference, Send, SendCopy, SendWith, and slice publishing. Requires setup with NodeBuilder and ServiceBuilder. ```csharp using Iceoryx2; using System.Runtime.InteropServices; using System.Threading; [StructLayout(LayoutKind.Sequential)] struct CounterData { public int Value; public long Timestamp; } using var node = NodeBuilder.New().Name("publisher").Create().Expect("node"); using var service = node.ServiceBuilder() .PublishSubscribe() .Open("MyCounter") .Expect("service"); using var publisher = service.CreatePublisher().Expect("publisher"); // Zero-copy path: loan → write → send var sample = publisher.Loan().Expect("loan failed"); sample.Payload = new CounterData { Value = 42, Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }; sample.Send().Expect("send failed"); // sample handle consumed after Send() // Zero-copy via mutable reference (true in-place write) using var sample2 = publisher.Loan().Expect("loan"); ref var payload = ref sample2.GetPayloadRef(); payload.Value = 100; payload.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); sample2.Send().Expect("send"); // Convenience: Send(T value) — loan + write + send in one call publisher.Send(new CounterData { Value = 7, Timestamp = 0 }).Expect("send"); // Convenience: SendCopy — marshals struct through unmanaged memory publisher.SendCopy(new CounterData { Value = 99, Timestamp = 0 }).Expect("sendcopy"); // SendWith: initializer callback avoids re-reading default value publisher.SendWith((ref CounterData p) => { p.Value = 55; p.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); }).Expect("sendWith"); // Slice publish: send an array of structs in one operation using var sliceSample = publisher.LoanSlice(3).Expect("loan slice"); var span = sliceSample.PayloadAsSpan; span[0] = new CounterData { Value = 1 }; span[1] = new CounterData { Value = 2 }; span[2] = new CounterData { Value = 3 }; sliceSample.Send().Expect("send slice"); // Publisher.UpdateConnections() — required after a late-joining subscriber // when the service was configured with history publisher.UpdateConnections().Expect("update connections"); ``` -------------------------------- ### Async Method Best Practice: Pass CancellationToken Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Demonstrates the importance of passing a `CancellationToken` to asynchronous operations for flexibility. The 'good' example includes a cancellation token, while the 'OK' example omits it, making the operation less flexible. ```csharp // ✅ GOOD: Cancellable operation public async Task WorkAsync(CancellationToken ct) { var response = await pendingResponse.ReceiveAsync(TimeSpan.FromSeconds(10), ct); } ``` ```csharp // ⚠️ OK but less flexible: No cancellation public async Task WorkAsync() { var response = await pendingResponse.ReceiveAsync(TimeSpan.FromSeconds(10)); } ``` -------------------------------- ### Build iceoryx2 C# Project Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ComplexDataTypes/README.md Command to build the iceoryx2 C# project, including the complex data types example. ```bash cd /path/to/iceoryx2-csharp dotnet build examples/ComplexDataTypes/ComplexDataTypes.csproj ``` -------------------------------- ### Run iceoryx2 C# Subscriber with TransmissionData Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ComplexDataTypes/README.md Command to run the subscriber example, expecting to receive TransmissionData. ```bash cd examples/ComplexDataTypes dotnet run --framework net9.0 -- subscriber TransmissionData ``` -------------------------------- ### Run Observer (net9.0) Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ObservableWaitSet/README.md Start the observer application to monitor multiple services using reactive streams with .NET 9.0. ```bash dotnet run --framework net9.0 -- observe service_a service_b ``` -------------------------------- ### Add iceoryx2.Reactive Project Reference Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/src/Iceoryx2.Reactive/README.md Example of how to add a project reference to the iceoryx2.Reactive project in your C# project. ```xml ``` -------------------------------- ### Async Method Best Practice: Async All The Way Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Illustrates the recommended practice of using `async` methods throughout the call chain to avoid blocking. The 'good' example uses `await` for asynchronous operations, while the 'bad' example shows a blocking call within an async method. ```csharp // ✅ GOOD: Async all the way public async Task ProcessDataAsync() { var response = await pendingResponse.ReceiveAsync(TimeSpan.FromSeconds(1)); // ... process response } ``` ```csharp // ❌ BAD: Blocking in async method public async Task ProcessDataAsync() { var response = pendingResponse.TimedReceive(TimeSpan.FromSeconds(1)); // Blocks! } ``` -------------------------------- ### Run Server for Request-Response Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/RequestResponse/README.md Runs the server process for the iceoryx2 request-response example. This command should be executed in one terminal. ```sh dotnet run -- server ``` -------------------------------- ### Run Client for Request-Response Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/RequestResponse/README.md Runs the client process for the iceoryx2 request-response example. This command should be executed in a separate terminal. ```sh dotnet run -- client ``` -------------------------------- ### Run Observer (net8.0) Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ObservableWaitSet/README.md Start the observer application to monitor multiple services using reactive streams with .NET 8.0. ```bash dotnet run --framework net8.0 -- observe service_a service_b ``` -------------------------------- ### File Logging via Custom Logger Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/Logging/README.md Illustrates implementing file logging using a custom logger callback, writing logs to a file and the console simultaneously. ```bash dotnet run --framework net9.0 -- file ``` -------------------------------- ### Run iceoryx2 C# Subscriber with Other Data Types Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ComplexDataTypes/README.md Commands to run the subscriber example, matching the publisher's data type (SensorData or PointData). ```bash dotnet run --framework net9.0 -- subscriber SensorData ``` ```bash dotnet run --framework net9.0 -- subscriber PointData ``` -------------------------------- ### Implement Request-Response Client and Server in C# Source: https://context7.com/eclipse-iceoryx/iceoryx2-csharp/llms.txt This snippet shows a complete example of a Request-Response service, including client and server implementations. It covers both the copy and zero-copy (loan) APIs for sending requests and responses. Ensure the Node, Service, and Client/Server are correctly configured and opened before use. ```csharp using Iceoryx2; using Iceoryx2.RequestResponse; using System.Runtime.InteropServices; using System.Threading; [StructLayout(LayoutKind.Sequential)] struct QueryRequest { public ulong RequestId; } [StructLayout(LayoutKind.Sequential)] struct QueryResponse { public int X; public int Y; public double Result; } // ---- CLIENT ---- using var clientNode = NodeBuilder.New().Name("client").Create().Expect("node"); using var clientService = clientNode.ServiceBuilder() .RequestResponse() .Open("My/Query/Service") .Expect("service"); using var client = clientService.CreateClient().Expect("client"); // Send via copy API → get pending response handle var pending = client.SendCopy(42UL).Expect("send request"); Thread.Sleep(100); // give server time to process // Poll for responses while (true) { var resp = pending.TryReceive(); if (!resp.IsOk) { Console.WriteLine($"Error: {resp}"); break; } var response = resp.Unwrap(); if (response == null) break; // no more responses using (response) Console.WriteLine($"Response: x={response.Payload.X}, y={response.Payload.Y}, result={response.Payload.Result:F2}"); } pending.Dispose(); // Zero-copy loan path using var reqSample = client.Loan().Expect("loan request"); reqSample.Payload = 99UL; using var pending2 = reqSample.Send().Expect("send loaned request"); // ---- SERVER ---- using var serverNode = NodeBuilder.New().Name("server").Create().Expect("node"); using var serverService = serverNode.ServiceBuilder() .RequestResponse() .Open("My/Query/Service") .Expect("service"); using var server = serverService.CreateServer().Expect("server"); int counter = 0; while (true) { var receiveResult = server.Receive(); if (!receiveResult.IsOk) break; var request = receiveResult.Unwrap(); if (request == null) { Thread.Sleep(10); continue; } using (request) { Console.WriteLine($"Received request: {request.Payload}"); var responseData = new QueryResponse { X = 5 + counter, Y = 6 * counter, Result = 7.77 }; request.SendCopyResponse(responseData).Expect("send response"); counter++; } } ``` -------------------------------- ### Run Publisher for Particle Data Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ArrayOfStructs/README.md Start the publisher application to send particle data. Specify the target framework (.NET 9.0 or .NET 8.0) using the --framework flag. ```bash dotnet run --framework net9.0 -- publisher particle ``` -------------------------------- ### Execute All Build Steps with Script Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/README.md A convenience script that automates the entire build process, including building the C FFI library, generating C# bindings, building the .NET solution, running tests, and building examples. ```bash ./build.sh ``` -------------------------------- ### Run Publisher for Sensor Data Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ArrayOfStructs/README.md Start the publisher application to send sensor data. Specify the target framework (.NET 9.0 or .NET 8.0) using the --framework flag. ```bash dotnet run --framework net9.0 -- publisher sensor ``` -------------------------------- ### Basic Console Logging Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/Logging/README.md Demonstrates setting the log level and writing messages using the default console logger. The console logger is automatically enabled in v0.8.0+. ```bash dotnet run --framework net9.0 -- basic ``` -------------------------------- ### Iceoryx2 Event Pattern Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Demonstrates creating a node, opening an event service, and using notifiers to send events and listeners to receive them via non-blocking, timed, and blocking waits. ```csharp using Iceoryx2; using Iceoryx2.Event; // Create a node var nodeResult = NodeBuilder.New() .Name("event_node") .Create(); if (!nodeResult.IsOk) { Console.WriteLine($"Failed to create node: {nodeResult}"); return; } using var node = nodeResult.Unwrap(); // Open or create an event service var serviceResult = node.ServiceBuilder() .Event() .Open("MyEventService"); if (!serviceResult.IsOk) { Console.WriteLine($"Failed to open event service: {serviceResult}"); return; } using var service = serviceResult.Unwrap(); // Notifier example (event sender) var notifierResult = service.CreateNotifier(defaultEventId: new EventId(100)); if (!notifierResult.IsOk) { Console.WriteLine($"Failed to create notifier: {notifierResult}"); return; } using var notifier = notifierResult.Unwrap(); var notifyResult = notifier.Notify(new EventId(5)); if (!notifyResult.IsOk) { Console.WriteLine($"Failed to notify: {notifyResult}"); } // Listener example (event receiver) var listenerResult = service.CreateListener(); if (!listenerResult.IsOk) { Console.WriteLine($"Failed to create listener: {listenerResult}"); return; } using var listener = listenerResult.Unwrap(); // Non-blocking wait var tryWaitResult = listener.TryWait(); if (!tryWaitResult.IsOk) { Console.WriteLine($"Failed to wait: {tryWaitResult}"); return; } var eventId = tryWaitResult.Unwrap(); if (eventId.HasValue) { Console.WriteLine($"Received event: {eventId.Value}"); } // Timed wait (1 second timeout) var timedWaitResult = listener.TimedWait(TimeSpan.FromSeconds(1)); if (!timedWaitResult.IsOk) { Console.WriteLine($"Failed to wait: {timedWaitResult}"); return; } var timedEventId = timedWaitResult.Unwrap(); if (timedEventId.HasValue) { Console.WriteLine($"Received event: {timedEventId.Value}"); } else { Console.WriteLine("Timeout - no event received"); } // Blocking wait var blockingWaitResult = listener.BlockingWait(); if (!blockingWaitResult.IsOk) { Console.WriteLine($"Failed to wait: {blockingWaitResult}"); return; } var blockingEventId = blockingWaitResult.Unwrap(); Console.WriteLine($"Received event: {blockingEventId}"); ``` -------------------------------- ### Zero-Copy Write with iceoryx2 Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/TaskCommunication/README.md Loan a sample from the publisher, get a reference to its payload, and write data directly to shared memory. Ensure to send the sample after writing. ```csharp var loanResult = publisher.Loan(); using var sample = loanResult.Unwrap(); // Direct zero-copy write to shared memory ref var data = ref sample.GetPayloadRef(); data.Temperature = 20.0 + random.NextDouble() * 10.0; data.Pressure = 1000.0 + random.NextDouble() * 50.0; sample.Send(); ``` -------------------------------- ### Imperative Polling Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/src/Iceoryx2.Reactive/README.md Demonstrates the traditional imperative polling approach for receiving data from a subscriber before adopting Rx. ```csharp while (true) { var result = subscriber.Receive(); if (result.IsOk) { var sample = result.Unwrap(); if (sample.HasValue) { using var s = sample.Value; // Process data Console.WriteLine($ ``` -------------------------------- ### Dispose Subscription Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ReactiveExample/README.md Demonstrates proper disposal of an observable subscription using a 'using' statement to ensure cleanup and stop polling tasks. ```csharp using var subscription = subscriber.AsObservable() .Where(data => data.Temperature > 28.0) .Subscribe(data => Console.WriteLine(data)); // subscription automatically disposed when out of scope ``` -------------------------------- ### Declarative Rx Stream Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/src/Iceoryx2.Reactive/README.md Shows how to use the Rx-style stream with IObservable for declarative data handling, including filtering and subscription. ```csharp using var subscription = subscriber.AsObservable() .Where(data => data.IsValid) .Subscribe(data => Console.WriteLine($"Received valid data: {data}")); Console.ReadKey(); // Keep the app alive ``` -------------------------------- ### Run Listener for Reactive Events Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ReactiveEventExample/README.md Starts the listener application to demonstrate various Rx operators on incoming events. This command should be run in Terminal 1. ```bash cd examples/ReactiveEventExample dotnet run --framework net9.0 -- listener events ``` -------------------------------- ### Custom Logger with Color Example Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/Logging/README.md Shows how to implement a custom logger callback to add timestamps and colored output to log messages. ```bash dotnet run --framework net9.0 -- custom ``` -------------------------------- ### Add iceoryx2 Package via NuGet Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/README.md Install the iceoryx2 NuGet package to include pre-built native libraries for macOS, Linux, and Windows. ```bash dotnet add package Iceoryx2 ``` -------------------------------- ### Publisher Cleanup with Using Statement Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/ARCHITECTURE.md This example demonstrates how to ensure deterministic cleanup of native resources managed by `SafeHandle`. The `using` statement guarantees that the publisher is disposed when the block is exited, preventing resource leaks. ```csharp // Using statement ensures cleanup using var publisher = service.CreatePublisher().Unwrap(); // Publisher automatically disposed here ``` -------------------------------- ### Run Subscriber for Particle Data Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ArrayOfStructs/README.md Start the subscriber application for particle data. Specify the target framework (.NET 9.0 or .NET 8.0) using the --framework flag. ```bash dotnet run --framework net9.0 -- subscriber particle ``` ```bash dotnet run --framework net8.0 -- subscriber particle ``` -------------------------------- ### Basic Observable Subscription (Polling-Based) Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/src/Iceoryx2.Reactive/README.md Sets up a basic polling-based observable subscription to receive data from a service. Requires Node, Service, and Subscriber setup. ```csharp using Iceoryx2; using Iceoryx2.Reactive; using System.Reactive.Linq; var node = NodeBuilder.New().Create().Expect("Failed to create node"); var service = node.ServiceBuilder() .PublishSubscribe() .Open("my_service") .Expect("Failed to open service"); var subscriber = service.CreateSubscriber() .Expect("Failed to create subscriber"); // Polling-based observable (simple) using var subscription = subscriber.AsObservable() .Subscribe(data => Console.WriteLine($"Received: {data}")); Console.ReadKey(); ``` -------------------------------- ### Open a Publish-Subscribe Service Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/ARCHITECTURE.md Services define communication channels with specific messaging patterns. This example opens a Publish-Subscribe service named 'sensor_data' for 'MyData'. Ensure 'MyData' meets zero-copy requirements. ```csharp var service = node.ServiceBuilder() .PublishSubscribe() .Open("sensor_data") .Unwrap(); ``` -------------------------------- ### Run Subscriber for Sensor Data Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ArrayOfStructs/README.md Start the subscriber application for sensor data. Specify the target framework (.NET 9.0 or .NET 8.0) using the --framework flag. ```bash dotnet run --framework net9.0 -- subscriber sensor ``` -------------------------------- ### Build the project Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/AsyncPubSub/README.md Use the dotnet CLI to build the project. ```bash dotnet build ``` -------------------------------- ### Run Multiple Concurrent Subscribers Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/AsyncPubSub/README.md Starts multiple subscriber applications to demonstrate concurrent data processing. ```bash # In another terminal dotnet run multi ``` -------------------------------- ### NodeBuilder - Create Application Entry Point Source: https://context7.com/eclipse-iceoryx/iceoryx2-csharp/llms.txt Demonstrates how to create a Node, which is the entry point for any iceoryx2 application. The NodeBuilder allows setting a human-readable name and provides a fluent interface for creating the Node. The `Create()` method returns a `Result` which can be handled explicitly or by using `.Expect()` to throw an exception on error. ```APIDOC ## NodeBuilder ### Description `NodeBuilder` is used to create the application entry point, a `Node`. It allows setting a human-readable name and returns a `Result` upon calling `Create()`. ### Method `NodeBuilder.New().Name("your_node_name").Create()` ### Parameters #### Method Parameters - **Name** (string) - Sets a human-readable name for the node. ### Return Value - `Result`: An object containing either the created `Node` or an `Iox2Error`. ### Usage Example ```csharp using Iceoryx2; // Create a named node (IPC service type by default) using var node = NodeBuilder.New() .Name("my_application") .Create() .Expect("Failed to create node"); // throws InvalidOperationException on error // Alternatively, handle the result explicitly var result = NodeBuilder.New().Name("my_app").Create(); if (!result.IsOk) { Console.WriteLine($"Node creation failed: {result}"); return; } using var node2 = result.Unwrap(); ``` ``` -------------------------------- ### List Available Services in C# Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Demonstrates how to list all running services and their basic information using the iceoryx2-csharp service discovery API. Requires creating a node to access discovery functionalities. ```csharp using Iceoryx2; // Create a node (required to access service discovery) using var node = NodeBuilder.New() .Name("discovery_node") .Create() .Unwrap(); // List all running services var services = node.List().Unwrap(); Console.WriteLine($"Found {services.Count} service(s):"); foreach (var service in services) { Console.WriteLine($" Service: {service.Name}"); Console.WriteLine($" ID: {service.Id}"); Console.WriteLine($" Pattern: {service.MessagingPattern}"); } ``` -------------------------------- ### Run the Blocking Subscriber Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/AsyncPubSub/README.md Starts a subscriber application that polls asynchronously until data arrives, without a specific timeout. ```bash # In another terminal dotnet run blocking ``` -------------------------------- ### Send Sensor Data Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ReactiveExample/README.md Example of sending sensor data using the publisher. Expects the send operation to succeed. ```csharp publisher.SendCopy(data).Expect("Failed to send sample"); ``` -------------------------------- ### Build iceoryx2-csharp Solution Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/README.md Builds the entire iceoryx2-csharp solution, including native libraries and all projects. This command is executed from the repository root. ```bash dotnet build --configuration Release ``` -------------------------------- ### Run Async Subscriber with Timeout Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Starts an asynchronous subscriber that will wait for messages with a timeout. This is useful for preventing indefinite blocking when no messages are expected. ```bash # Terminal 2 - Async subscriber with timeout dotnet run --framework net9.0 subscriber ``` -------------------------------- ### Run Notifier for Reactive Events Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ReactiveEventExample/README.md Starts the notifier application to send various event types to the listener. This command should be run in Terminal 2. ```bash cd examples/ReactiveEventExample dotnet run --framework net9.0 -- notifier events ``` -------------------------------- ### C# Memory Management Best Practices Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Illustrates recommended practices for managing native resources in C# using iceoryx2, emphasizing the use of `using` statements for automatic disposal and contrasting it with manual disposal in a try-finally block. It also shows an anti-pattern of relying solely on finalizers. ```csharp // ✅ GOOD: Using statement ensures disposal using var node = NodeBuilder.New().Create().Unwrap(); using var service = node.ServiceBuilder().Event().Open("MyService").Unwrap(); using var notifier = service.CreateNotifier().Unwrap(); ``` ```csharp // ✅ GOOD: Explicit disposal in try-finally var node = NodeBuilder.New().Create().Unwrap(); try { // Use node... } finally { node.Dispose(); } ``` ```csharp // ❌ BAD: No disposal - relies on finalizer (slower, not deterministic) var node = NodeBuilder.New().Create().Unwrap(); // ... use node without disposing ``` -------------------------------- ### Create Application Entry Point with NodeBuilder Source: https://context7.com/eclipse-iceoryx/iceoryx2-csharp/llms.txt Use NodeBuilder to create a named node, which is the entry point for all iceoryx2 applications. The node owns all services created from it and must outlive them. Handles errors explicitly or by expecting success. ```csharp using Iceoryx2; // Create a named node (IPC service type by default) using var node = NodeBuilder.New() .Name("my_application") .Create() .Expect("Failed to create node"); // throws InvalidOperationException on error // Alternatively, handle the result explicitly var result = NodeBuilder.New().Name("my_app").Create(); if (!result.IsOk) { Console.WriteLine($"Node creation failed: {result}"); return; } using var node2 = result.Unwrap(); ``` -------------------------------- ### Configure Log Level from Environment Variable Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/Logging/README.md Demonstrates setting the log level using the IOX2_LOG_LEVEL environment variable, with options for a custom default value. ```csharp // Set log level from IOX2_LOG_LEVEL environment variable, default to Info Iox2Log.SetLogLevelFromEnvOrDefault(); // Or with custom default Iox2Log.SetLogLevelFromEnvOr(LogLevel.Debug); ``` -------------------------------- ### Define Sensor Data Structure Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ReactiveExample/README.md Defines the structure for sensor data, including temperature, humidity, and timestamp. This structure is used throughout the reactive examples. ```csharp struct SensorData { public double Temperature; public double Humidity; public int Timestamp; } ``` -------------------------------- ### Build Native Library Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/CONTRIBUTING.md Build the native iceoryx2-ffi-c library using Cargo. This is a prerequisite for building the C# bindings. ```bash cargo build --release --package iceoryx2-ffi-c ``` -------------------------------- ### Get Blackboard Entry Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/Blackboard/README.md Use this code to retrieve the latest value of a specific entry from the blackboard. Ensure the `SensorData` struct and `SensorKey` enum are defined and accessible. ```csharp var entry = reader.Entry(SensorKey.Temperature); var data = entry.Get(); ``` -------------------------------- ### Async Request-Response Client Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Demonstrates how to create an asynchronous client to send requests and receive responses using the iceoryx2 C# bindings. Ensure the service is opened with the correct request-response type. ```csharp using System; using System.Threading; using System.Threading.Tasks; using Iceoryx2; using Iceoryx2.RequestResponse; public async Task RunClientAsync(CancellationToken cancellationToken = default) { // Create node and service (same as sync version) var node = NodeBuilder.New() .Name("async_client") .Create() .Unwrap(); using var service = node.ServiceBuilder() .RequestResponse() .Open("MyService") .Unwrap(); using var client = service.CreateClient().Unwrap(); // Send request var sendResult = client.SendCopy(42ul); using var pendingResponse = sendResult.Unwrap(); // Wait for response asynchronously with timeout var responseResult = await pendingResponse.ReceiveAsync( TimeSpan.FromSeconds(2), cancellationToken); if (responseResult.IsOk) { var response = responseResult.Unwrap(); if (response != null) { using (response) { Console.WriteLine($"Received: {response.Payload}"); } } else { Console.WriteLine("Request timed out"); } } } ``` -------------------------------- ### Set Log Level via Environment Variable (Bash) Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/Logging/README.md Examples of setting the log level using the IOX2_LOG_LEVEL environment variable in a bash shell before running the application. ```bash # Set to Debug level export IOX2_LOG_LEVEL=DEBUG dotnet run --framework net9.0 -- basic # Set to Trace level (most verbose) export IOX2_LOG_LEVEL=TRACE dotnet run --framework net9.0 -- basic # Set to Warn level (less verbose) export IOX2_LOG_LEVEL=WARN dotnet run --framework net9.0 -- basic ``` -------------------------------- ### Build C# Bindings Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/README.md Build the C# project using the .NET CLI. The build process automatically copies the native library. ```bash # From repository root dotnet build ``` -------------------------------- ### Define Invalid Struct with Managed Type (String) Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ComplexDataTypes/README.md This example demonstrates an invalid struct definition for iceoryx2 because it contains a managed type (string), which violates the unmanaged constraint. ```csharp // ✗ Invalid - contains managed type (string) public struct InvalidData { public int Id; public string Name; // ERROR: string is a managed type } ``` -------------------------------- ### Build C# Bindings Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/CONTRIBUTING.md Build the C# bindings for iceoryx2 after the native library has been built. Ensure you are in the correct directory. ```bash cd iceoryx2-ffi/csharp && dotnet build ``` -------------------------------- ### Async Method Best Practice: ConfigureAwait(false) Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/README.md Shows how to use `ConfigureAwait(false)` in library code to avoid capturing the `SynchronizationContext`, which can prevent deadlocks and improve performance. ```csharp // In library code, avoid capturing SynchronizationContext var response = await pendingResponse .ReceiveAsync(timeout, ct) .ConfigureAwait(false); ``` -------------------------------- ### Migrating from Callback to Async Foreach Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/WaitSetAsyncEnumerable/README.md Illustrates the replacement of the old WaitSet callback pattern with the new async foreach loop. ```csharp // Old: var result = waitSet.WaitAndProcess(attachmentId => { // ... complex callback logic ... return CallbackProgression.Continue; }); // New: await foreach (var evt in waitSet.Events(cancellationToken)) { // ... simple event handling ... } ``` -------------------------------- ### Build iceoryx2 Native Library Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/README.md Build the iceoryx2 C FFI library using Cargo. This must be completed before building the C# project. ```bash # From repository root cd iceoryx2 cargo build --release --package iceoryx2-ffi-c cd .. ``` -------------------------------- ### Define Valid Unmanaged Struct for iceoryx2 Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ComplexDataTypes/README.md Structs used with iceoryx2 must be unmanaged, containing only primitive types or other unmanaged types. This example shows a valid SensorData struct. ```csharp // ✓ Valid unmanaged types public struct SensorData { public long Timestamp; public float Temperature; public float Humidity; public int SensorId; } ``` -------------------------------- ### Receive Data with iceoryx2 Subscriber Source: https://context7.com/eclipse-iceoryx/iceoryx2-csharp/llms.txt Demonstrates various ways to receive data samples using the iceoryx2 Subscriber. Includes synchronous non-blocking, convenience methods like TryReceiveValue and ProcessSample, and asynchronous receiving with and without timeouts. Remember to dispose of samples to release memory slots. ```csharp using Iceoryx2; using System.Threading; using System.Threading.Tasks; [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] struct CounterData { public int Value; public long Timestamp; } using var node = NodeBuilder.New().Name("subscriber").Create().Expect("node"); using var service = node.ServiceBuilder() .PublishSubscribe() .Open("MyCounter") .Expect("service"); using var subscriber = service.SubscriberBuilder().Create().Expect("subscriber"); // Synchronous non-blocking receive var result = subscriber.Receive(); if (result.IsOk) { using var sample = result.Unwrap(); // null if no data available if (sample != null) Console.WriteLine($"Value={sample.Payload.Value}"); } // Convenience: TryReceiveValue — get payload directly without managing Sample lifetime var valueResult = subscriber.TryReceiveValue(); if (valueResult.IsOk && valueResult.Unwrap().HasValue) Console.WriteLine($"Got: {valueResult.Unwrap()!.Value.Value}"); // Convenience: ProcessSample — callback-based receive, auto-disposes sample subscriber.ProcessSample(data => Console.WriteLine($"Processed: {data.Value}")); // Async with timeout (polls every 10ms, yields to thread pool) var cts = new CancellationTokenSource(); var asyncResult = await subscriber.ReceiveAsync(TimeSpan.FromSeconds(5), cts.Token); if (asyncResult.IsOk) { using var asyncSample = asyncResult.Unwrap(); if (asyncSample != null) Console.WriteLine($"Async received: {asyncSample.Payload.Value}"); else Console.WriteLine("Timeout - no sample in 5s"); } // Async blocking (no timeout, waits until data arrives) var blockingResult = await subscriber.ReceiveAsync(cts.Token); using var blockingSample = blockingResult.Unwrap(); Console.WriteLine($"Blocking received: {blockingSample.Payload.Value}"); // Multiple concurrent subscribers from the same node + service using var sub2 = service.SubscriberBuilder().Create().Expect("sub2"); using var sub3 = service.SubscriberBuilder().Create().Expect("sub3"); await Task.WhenAll( subscriber.ReceiveAsync(cts.Token).ContinueWith(t => Console.WriteLine($"[sub1] {t.Result.Unwrap()?.Payload.Value}")), sub2.ReceiveAsync(cts.Token).ContinueWith(t => Console.WriteLine($"[sub2] {t.Result.Unwrap()?.Payload.Value}")) ); ``` -------------------------------- ### Zero-Copy Read with iceoryx2 Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/TaskCommunication/README.md Receive a sample, unwrap it to get access to the payload, and read data directly from shared memory using a read-only reference. The sample is automatically released when disposed. ```csharp var sample = receiveResult.Unwrap(); using (sample) { // Direct zero-copy read from shared memory ref readonly var data = ref sample.GetPayloadRefReadOnly(); samples.Add(data); } ``` -------------------------------- ### Receive Event Notifications with Listener Source: https://context7.com/eclipse-iceoryx/iceoryx2-csharp/llms.txt Demonstrates non-blocking, timed, and blocking waits for event notifications using iceoryx2's Listener. Includes an example of an asynchronous wait and draining pending events. ```csharp using Iceoryx2; using System.Threading; using System.Threading.Tasks; using var node = NodeBuilder.New().Name("listener").Create().Expect("node"); using var service = node.ServiceBuilder() .Event() .Open("MyEventService") .Expect("service"); using var listener = service.CreateListener().Expect("listener"); // Non-blocking: returns null if no event pending var tryResult = listener.TryWait(); if (tryResult.IsOk && tryResult.Unwrap().HasValue) Console.WriteLine($"Event id: {tryResult.Unwrap()!.Value.Value}"); // Timed wait: blocks up to timeout var timedResult = listener.TimedWait(TimeSpan.FromSeconds(1)); if (timedResult.IsOk) { var eventId = timedResult.Unwrap(); Console.WriteLine(eventId.HasValue ? $"Got: {eventId.Value.Value}" : "Timeout"); } // Blocking wait: blocks until an event arrives var blockingResult = listener.BlockingWait(); if (blockingResult.IsOk) Console.WriteLine($"Blocking received: {blockingResult.Unwrap().Value}"); // Async wait (runs on background thread, does not block caller) var cts = new CancellationTokenSource(); var asyncResult = await listener.WaitAsync(TimeSpan.FromSeconds(5), cts.Token); // Drain all pending events in a loop (required when used with WaitSet) while (true) { var ev = listener.TryWait(); if (!ev.IsOk || !ev.Unwrap().HasValue) break; Console.WriteLine($"Drained event: {ev.Unwrap()!.Value.Value}"); } ``` -------------------------------- ### Rust and C# Cross-Language Struct Compatibility Source: https://github.com/eclipse-iceoryx/iceoryx2-csharp/blob/main/examples/ComplexDataTypes/README.md Example demonstrating how to define equivalent structs in Rust and C# for cross-language communication, ensuring matching type names, memory layout, and field types. ```rust #[repr(C)] struct TransmissionData { x: i32, y: i32, funky: f64, } ``` ```csharp [StructLayout(LayoutKind.Sequential)] [Iox2Type("TransmissionData")] public struct TransmissionData { public int X; // i32 in Rust public int Y; // i32 in Rust public double Funky; // f64 in Rust } ```