From 579fbef812b7ad925aa22a4f58748f5368e8f085 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 16 Jul 2025 21:15:46 -0700 Subject: [PATCH 1/4] Revise C# language support section Added more details where necessary. Factored code examples out into separate files and included them. Fixed a bug where the package name in the Program.cs file (in the "host-app" project) didn't match the package name in the .wit Factored out duplicated text in "Run the component from the example host" section that also appears in the C section; included this text from separate .md files. --- .../tutorial/csharp/adder/Component.cs | 9 + .../tutorial/csharp/adder/Component2.cs | 9 + .../examples/tutorial/csharp/adder/Program.cs | 8 + .../tutorial/csharp/adder/world-hostapp.wit | 13 ++ component-model/src/language-support/c.md | 46 +--- .../src/language-support/csharp.md | 207 +++++++----------- .../language-support/example-host-part1.md | 15 ++ .../language-support/example-host-part2.md | 29 +++ 8 files changed, 160 insertions(+), 176 deletions(-) create mode 100644 component-model/examples/tutorial/csharp/adder/Component.cs create mode 100644 component-model/examples/tutorial/csharp/adder/Component2.cs create mode 100644 component-model/examples/tutorial/csharp/adder/Program.cs create mode 100644 component-model/examples/tutorial/csharp/adder/world-hostapp.wit create mode 100644 component-model/src/language-support/example-host-part1.md create mode 100644 component-model/src/language-support/example-host-part2.md diff --git a/component-model/examples/tutorial/csharp/adder/Component.cs b/component-model/examples/tutorial/csharp/adder/Component.cs new file mode 100644 index 00000000..1f5fd2e1 --- /dev/null +++ b/component-model/examples/tutorial/csharp/adder/Component.cs @@ -0,0 +1,9 @@ +namespace AdderWorld; + +public class AddImpl : IAdderWorld +{ + public static uint Add(uint x, uint y) + { + return x + y; + } +} diff --git a/component-model/examples/tutorial/csharp/adder/Component2.cs b/component-model/examples/tutorial/csharp/adder/Component2.cs new file mode 100644 index 00000000..e880b933 --- /dev/null +++ b/component-model/examples/tutorial/csharp/adder/Component2.cs @@ -0,0 +1,9 @@ +namespace ExampleWorld.wit.exports.docs.adder.v0_1_0; + +public class AddImpl : IAdd +{ + public static uint Add(uint x, uint y) + { + return x + y; + } +} diff --git a/component-model/examples/tutorial/csharp/adder/Program.cs b/component-model/examples/tutorial/csharp/adder/Program.cs new file mode 100644 index 00000000..5088bcb1 --- /dev/null +++ b/component-model/examples/tutorial/csharp/adder/Program.cs @@ -0,0 +1,8 @@ +// Pull in all imports of the `hostapp` world, namely the `add` interface. +// example.component refers to the package name defined in the WIT file. +using HostappWorld.wit.imports.docs.adder.v0_1_0; + +uint left = 1; +uint right = 2; +var result = AddInterop.Add(left, right); +Console.WriteLine($"{left} + {right} = {result}"); diff --git a/component-model/examples/tutorial/csharp/adder/world-hostapp.wit b/component-model/examples/tutorial/csharp/adder/world-hostapp.wit new file mode 100644 index 00000000..0f172bd6 --- /dev/null +++ b/component-model/examples/tutorial/csharp/adder/world-hostapp.wit @@ -0,0 +1,13 @@ +package docs:adder@0.1.0; + +interface add { + add: func(x: u32, y: u32) -> u32; +} + +world example { + export add; +} + +world hostapp { + import add; +} diff --git a/component-model/src/language-support/c.md b/component-model/src/language-support/c.md index f001ac92..ccc5541e 100644 --- a/component-model/src/language-support/c.md +++ b/component-model/src/language-support/c.md @@ -321,56 +321,14 @@ The following section requires you to have [a Rust toolchain][rust] installed. > (The `wasmtime` version is specified in [the Cargo configuration file][cargo-config] > for the example host.) -This repository contains an [example WebAssembly host][example-host] written in Rust -that can run components that implement the `adder` world. - -1. `git clone https://github.com/bytecodealliance/component-docs.git` -2. `cd component-docs/component-model/examples/example-host` -3. `cargo run --release -- 1 2 /adder.wasm` -* The double dashes separate the flags passed to `cargo` from - the flags passed in to your code. -* The arguments 1 and 2 are the arguments to the adder. -* In place of ``, substitute the directory that contains your - generated `adder.wasm` file (or `adder.component.wasm` if you used - the manual instructions). - -> [!NOTE] -> When hosts run components that use WASI interfaces, they must *explicitly* -> [add WASI to the linker][add-to-linker] to run the built component. +{{#include example-host-part1.md}} A successful run should show the following output (of course, the paths to your example host and adder component will vary, and you should substitute `adder.wasm` with `adder.component.wasm` if you followed the manual instructions above): -``` -cargo run --release -- 1 2 adder.wasm - Compiling example-host v0.1.0 (/path/to/component-docs/component-model/examples/example-host) - Finished `release` profile [optimized] target(s) in 7.85s - Running `target/debug/example-host 1 2 /path/to/adder.wasm` -1 + 2 = 3 -``` - -If *not* configured correctly, you may see errors like the following: - -``` -cargo run --release -- 1 2 adder.wasm - Compiling example-host v0.1.0 (/path/to/component-docs/component-model/examples/example-host) - Finished `release` profile [optimized] target(s) in 7.85s - Running `target/release/example-host 1 2 /path/to/adder.component.wasm` -Error: Failed to instantiate the example world - -Caused by: - 0: component imports instance `wasi:io/error@0.2.2`, but a matching implementation was not found in the linker - 1: instance export `error` has the wrong type - 2: resource implementation is missing -``` - -This kind of error normally indicates that the host in question does not satisfy WASI imports. - -[host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host -[add-to-linker]: https://docs.wasmtime.dev/api/wasmtime_wasi/p2/fn.add_to_linker_sync.html -[example-host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host +{{#include example-host-part2.md}} ## 7. Run the component from C/C++ Applications diff --git a/component-model/src/language-support/csharp.md b/component-model/src/language-support/csharp.md index abeb2420..d4132aa1 100644 --- a/component-model/src/language-support/csharp.md +++ b/component-model/src/language-support/csharp.md @@ -1,8 +1,8 @@ # C# Tooling WebAssembly components in C# can be built with [componentize-dotnet][componentize-dotnet], -a a NuGet package that can be used to create a fully AOT-compiled -component, giving .NET developers a component experience comparable to those in Rust and TinyGo. +a NuGet package that can be used to create a fully ahead-of-time-compiled component, +giving .NET developers a component experience comparable to those in Rust and TinyGo. [componentize-dotnet]: https://github.com/bytecodealliance/componentize-dotnet @@ -18,9 +18,11 @@ component, giving .NET developers a component experience comparable to those in First, install the .NET SDK. For this walkthrough, we’ll use the [.NET 10 SDK preview][dotnet-sdk]. You should also have [wasmtime](https://wasmtime.dev/) installed so you can run the binary that you produce. +You will also need to install [wac][wac] for composing components. [dotnet-sdk]: https://dotnet.microsoft.com/en-us/download/dotnet/10.0 [wasmtime]: https://wasmtime.dev/ +[wac]: https://github.com/bytecodealliance/wac ## 1. Create a new project @@ -36,21 +38,15 @@ cd adder Next, create or download the WIT world you would like to target. -For this example we will use the [`adder` world][adder-world], with an `add` function (e.g. to `wit/component.wit`): +For this example we will use the [`adder` world][adder-world], with an `add` function. +Copy and paste the following into a new file called "`wit/component.wit`". ```wit -package docs:adder@0.1.0; - -interface add { - add: func(x: u32, y: u32) -> u32; -} - -world adder { - export add; -} +{{#include ../../examples/tutorial/wit/adder/world.wit}} ``` -In the `adder.csproj` project file, add a new ``: +In the `adder.csproj` project file, add a new `` +at the same level as the existing ``: ```xml @@ -58,7 +54,7 @@ In the `adder.csproj` project file, add a new ``: ``` -Since this component will only export a function dotnet considers this a library project. +Since this component will only export a function, dotnet considers this a library project. Let's update the `` to be a library in the `adder.csproj`: ```diff @@ -90,18 +86,10 @@ Build failed with 1 error(s) in 34.6s This is because we've promised an implementation, but haven't yet written one for the `adder` world. -To fix this, add the following code to your in a file called `Component.cs`: +To fix this, add the following code in a file called `Component.cs`: ```csharp -namespace AdderWorld; - -public class AddImpl : IAdderWorld -{ - public static uint Add(uint x, uint y) - { - return x + y; - } -} +{{#include ../../examples/tutorial/csharp/adder/Component.cs}} ``` Then, we can build our component: @@ -112,90 +100,50 @@ dotnet build The component will be available at `bin/Debug/net10.0/wasi-wasm/native/adder.wasm`. -### 5. (optional) the component from the example host +### 4. (optional) Run the component from the example host -> [!WARNING] -> You must be careful to use a version of the adapter (`wasi_snapshot_preview1.wasm`) that is compatible with the version of -> `wasmtime` that will be used, to ensure that WASI interface versions (and relevant implementation) match. +The following section requires you to have [a Rust toolchain][rust] installed. -This repository contains an [example WebAssembly host][example-host] written in Rust that can run components that implement the `adder` world. +{{#include example-host-part1.md}} -> [!NOTE] -> When hosts run components that use WASI interfaces, they must *explicitly* [add WASI to the linker][add-to-linker] to run the built component. +A successful run should show the following output +(of course, the paths to your example host and adder component will vary): -A successful run should show the following output: +{{#include example-host-part2.md}} -``` -cargo run --release -- 1 2 adder.component.wasm - Compiling example-host v0.1.0 (/path/to/component-docs/component-model/examples/example-host) - Finished `release` profile [optimized] target(s) in 7.85s - Running `target/debug/example-host 1 2 /tmp/docs/c/adder.component.wasm` -1 + 2 = 3 -``` - -If *not* configured correctly, you may see errors like the following: - -``` -cargo run --release -- 1 2 adder.component.wasm - Compiling example-host v0.1.0 (/path/to/component-docs/component-model/examples/example-host) - Finished `release` profile [optimized] target(s) in 7.85s - Running `target/release/example-host 1 2 adder.component.wasm` -Error: Failed to instantiate the example world - -Caused by: - 0: component imports instance `wasi:io/error@0.2.2`, but a matching implementation was not found in the linker - 1: instance export `error` has the wrong type - 2: resource implementation is missing -``` - -This kind of error normally indicates that the host in question does not contain satisfy WASI imports. - -[host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host -[add-to-linker]: https://docs.wasmtime.dev/api/wasmtime_wasi/fn.add_to_linker_sync.html -[example-host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host +[rust]: https://www.rust-lang.org/learn/get-started ## Building a component that exports an interface -The previous example uses a WIT file that exports a function. However, you'll often prefer to export an interface, -either to comply with an existing specification or to capture a set of functions and types that tend to go -together. Let's expand our `example` world to export an interface rather than directly -export the function. We are also adding the `hostapp` world to our WIT file which we will implement -in [the next section](#building-a-component-that-imports-an-interface) to demonstrate how to build a -component that *imports* an interface. +The previous example uses a WIT file that exports a function. +However, you'll often prefer to export an interface, +either to comply with an existing specification +or to capture a set of functions and types that tend to go together. +Let's expand our `example` world to export an interface rather than directly export the function. +We are also adding the `hostapp` world to our WIT file, +which we will implement in [the next section](#building-a-component-that-imports-an-interface) +to demonstrate how to build a component that *imports* an interface. -```wit -// adder/world.wit -package example:component; +Edit your `wit/component.wit` file to look like this: -interface add { - add: func(x: u32, y: u32) -> u32; -} +```wit +{{#include ../../examples/tutorial/csharp/adder/world-hostapp.wit}} +``` -world example { - export add; -} +In our `Component.cs` example, we change the `namespace` declaration +to refer to the package name in the `wit/component.wit` file, +and change the `AddImpl` class so that it implements the `add` interface: -world hostapp { - import add; -} +```csharp +{{#include ../../examples/tutorial/csharp/adder/Component2.cs}} ``` -If you peek at the bindings, you'll notice that we now implement a class for the `add` interface -rather than for the `example` world -- this is a consistent pattern. As you export more interfaces -from your world, you implement more classes. - -Our `Component.cs` example gets the slight update of: +You also need to edit your `adder.csproj` project file as follows, +to reflect that we are now implementing the `example` world: -```csharp -namespace ExampleWorld.wit.exports.example.component; - -public class AddImpl : IAdd -{ - public static uint Add(uint x, uint y) - { - return x + y; - } -} +```diff +- ++ ``` Once again, compile an application to a Wasm component using `dotnet build`: @@ -211,18 +159,23 @@ Build succeeded in 2.5s The component will be available at `bin/Debug/net10.0/wasi-wasm/native/adder.wasm`. +If you peek at the bindings, you'll notice that we now implement a class for the `add` interface +rather than for the `example` world—this is a consistent pattern. +As you export more interfaces from your world, you implement more classes. + ## Building a component that imports an interface -So far, we've been dealing with library components. Now we will be creating a command component that -implements the `hostapp` world. This component will import the `add` interface that is exported from -our `adder` component and call the `add` function. We will later compose this command component with -the `adder` library component we just built. +So far, we've been dealing with library components. +Now we will be creating a command component that implements the `hostapp` world. +This component will import the `add` interface that is exported from our `adder` component +and call the `add` function. +We will later compose this command component with the `adder` library component we just built. Now we will be taking the `adder` component and executing it from another WebAssembly component. `dotnet new componentize.wasi.cli` creates a new project that creates an executable. -Back out of the current project and create a new one: +Change to the parent directory of your current project and create a new project: ```sh cd .. @@ -230,48 +183,29 @@ dotnet new componentize.wasi.cli -o host-app cd host-app ``` -Copy the same WIT file as before into your project: +Copy the following WIT file into a file called `wit/add.wit` in your project: ```wit -// adder/world.wit -package example:component; - -interface add { - add: func(x: u32, y: u32) -> u32; -} - -world example { - export add; -} - -world hostapp { - import add; -} +{{#include ../../examples/tutorial/csharp/adder/world-hostapp.wit}} ``` -Add it to your `host-app.csproj` project file as a new `ItemGroup`: +Add it to your `host-app.csproj` project file as a new `ItemGroup` at the top level: ```xml - + ``` -Notice how the `World` changed from `example` to `hostapp`. The previous examples focused on -implementing the class library for this WIT file - the `export` functions. Now we'll be focusing on -the executable side of the application - the `hostapp` world. +Notice how the `World` changed from `example` to `hostapp`. +The previous examples focused on implementing the class library +for this WIT file—the `export` functions. +Now we'll be focusing on the executable side of the application—the `hostapp` world. Modify `Program.cs` to look like this: ```csharp -// Pull in all imports of the `hostapp` world, namely the `add` interface. -// example.component refers to the package name defined in the WIT file. -using HostappWorld.wit.imports.example.component; - -uint left = 1; -uint right = 2; -var result = AddInterop.Add(left, right); -Console.WriteLine($"{left} + {right} = {result}"); +{{#include ../../examples/tutorial/csharp/adder/Program.cs}} ``` Once again, compile your component with `dotnet build`: @@ -285,14 +219,15 @@ You are using a preview version of .NET. See: https://aka.ms/dotnet-support-poli Build succeeded in 2.5s ``` -At this point, you'll have two Webassembly components: +At this point, you'll have two WebAssembly components: 1. A component that implements the `example` world. 2. A component that implements the `hostapp` world. -Since the `host-app` component depends on the `add` function which is defined in the `example` -world, it needs to be composed the first component. You can compose your `host-app` component with -your `adder` component by running [`wac plug`](https://github.com/bytecodealliance/wac): +Since the `host-app` component depends on the `add` function which is defined in the `example` world, +it needs to be composed with the first component. +You can compose your `host-app` component with your `adder` component +by running [`wac plug`](https://github.com/bytecodealliance/wac): ```sh wac plug \ @@ -301,6 +236,11 @@ wac plug \ -o main.wasm ``` +If you get an error message like "error: the socket component had no matching imports +for the plugs that were provided", +make sure that the package names in both .wit files +(the one for your `adder` component and the one for your `host-app` component) are the same. + You can also automate the process by adding the following to your `host-app.csproj`: ```xml @@ -314,7 +254,10 @@ You can also automate the process by adding the following to your `host-app.cspr ``` -Run `dotnet build` again you will have a composed component in `./dist/main.wasm` +This requires your original `adder.wasm` component to be in `../adder` +relative to the directory your `host-app` component is in. + +If you run `dotnet build` again, you will have a composed component in `./dist/main.wasm`. Then you can run the composed component: @@ -323,7 +266,7 @@ wasmtime run ./dist/main.wasm 1 + 2 = 3 ``` -Check out the [componentize-dotnet docs][componentize-dotnet-docs] for more configurations options. +Check out the [componentize-dotnet docs][componentize-dotnet-docs] for more configuration options. [componentize-dotnet-docs]: https://github.com/bytecodealliance/componentize-dotnet diff --git a/component-model/src/language-support/example-host-part1.md b/component-model/src/language-support/example-host-part1.md new file mode 100644 index 00000000..d9756bf5 --- /dev/null +++ b/component-model/src/language-support/example-host-part1.md @@ -0,0 +1,15 @@ +This repository contains an [example WebAssembly host][example-host] written in Rust +that can run components that implement the `adder` world. + +1. `git clone https://github.com/bytecodealliance/component-docs.git` +2. `cd component-docs/component-model/examples/example-host` +3. `cargo run --release -- 1 2 /adder.wasm` +* The double dashes separate the flags passed to `cargo` from + the flags passed in to your code. +* The arguments 1 and 2 are the arguments to the adder. +* In place of ``, substitute the directory that contains your + generated `adder.wasm` file. + +> Note: +> When hosts run components that use WASI interfaces, they must *explicitly* +> [add WASI to the linker][add-to-linker] to run the built component. diff --git a/component-model/src/language-support/example-host-part2.md b/component-model/src/language-support/example-host-part2.md new file mode 100644 index 00000000..0d3234c5 --- /dev/null +++ b/component-model/src/language-support/example-host-part2.md @@ -0,0 +1,29 @@ + +``` +cargo run --release -- 1 2 adder.wasm + Compiling example-host v0.1.0 (/path/to/component-docs/component-model/examples/example-host) + Finished `release` profile [optimized] target(s) in 7.85s + Running `target/debug/example-host 1 2 /path/to/adder.wasm` +1 + 2 = 3 +``` + +If *not* configured correctly, you may see errors like the following: + +``` +cargo run --release -- 1 2 adder.wasm + Compiling example-host v0.1.0 (/path/to/component-docs/component-model/examples/example-host) + Finished `release` profile [optimized] target(s) in 7.85s + Running `target/release/example-host 1 2 /path/to/adder.component.wasm` +Error: Failed to instantiate the example world + +Caused by: + 0: component imports instance `wasi:io/error@0.2.2`, but a matching implementation was not found in the linker + 1: instance export `error` has the wrong type + 2: resource implementation is missing +``` + +This kind of error normally indicates that the host in question does not satisfy WASI imports. + +[host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host +[add-to-linker]: https://docs.wasmtime.dev/api/wasmtime_wasi/p2/fn.add_to_linker_sync.html +[example-host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host From 5042b47a2b5e6356c454008f9962ef5e9bf6b760 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 15 Aug 2025 21:32:09 -0700 Subject: [PATCH 2/4] Update component-model/src/language-support/csharp.md Co-authored-by: Victor Adossi <123968127+vados-cosmonic@users.noreply.github.com> --- component-model/src/language-support/csharp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component-model/src/language-support/csharp.md b/component-model/src/language-support/csharp.md index d4132aa1..9196d9b1 100644 --- a/component-model/src/language-support/csharp.md +++ b/component-model/src/language-support/csharp.md @@ -54,7 +54,7 @@ at the same level as the existing ``: ``` -Since this component will only export a function, dotnet considers this a library project. +Since this component will only export functionality, dotnet considers this a library project. Let's update the `` to be a library in the `adder.csproj`: ```diff From 86744f1921d47857cd5a9cbf5e188408c9adf894 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 15 Aug 2025 21:58:10 -0700 Subject: [PATCH 3/4] Put error message in code block --- component-model/src/language-support/csharp.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/component-model/src/language-support/csharp.md b/component-model/src/language-support/csharp.md index 9196d9b1..0b46e685 100644 --- a/component-model/src/language-support/csharp.md +++ b/component-model/src/language-support/csharp.md @@ -236,9 +236,13 @@ wac plug \ -o main.wasm ``` -If you get an error message like "error: the socket component had no matching imports -for the plugs that were provided", -make sure that the package names in both .wit files +If you get an error message like: + +``` +error: the socket component had no matching imports for the plugs that were provided +``` + +then make sure that the package names in both .wit files (the one for your `adder` component and the one for your `host-app` component) are the same. You can also automate the process by adding the following to your `host-app.csproj`: From 776c8d7e4c50e66e7ca720096b4569b0f102f831 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 15 Aug 2025 22:20:23 -0700 Subject: [PATCH 4/4] Remove extra example --- .../tutorial/csharp/adder/Component.cs | 4 +- .../tutorial/csharp/adder/Component2.cs | 9 --- .../src/language-support/csharp.md | 61 ++----------------- 3 files changed, 7 insertions(+), 67 deletions(-) delete mode 100644 component-model/examples/tutorial/csharp/adder/Component2.cs diff --git a/component-model/examples/tutorial/csharp/adder/Component.cs b/component-model/examples/tutorial/csharp/adder/Component.cs index 1f5fd2e1..e880b933 100644 --- a/component-model/examples/tutorial/csharp/adder/Component.cs +++ b/component-model/examples/tutorial/csharp/adder/Component.cs @@ -1,6 +1,6 @@ -namespace AdderWorld; +namespace ExampleWorld.wit.exports.docs.adder.v0_1_0; -public class AddImpl : IAdderWorld +public class AddImpl : IAdd { public static uint Add(uint x, uint y) { diff --git a/component-model/examples/tutorial/csharp/adder/Component2.cs b/component-model/examples/tutorial/csharp/adder/Component2.cs deleted file mode 100644 index e880b933..00000000 --- a/component-model/examples/tutorial/csharp/adder/Component2.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ExampleWorld.wit.exports.docs.adder.v0_1_0; - -public class AddImpl : IAdd -{ - public static uint Add(uint x, uint y) - { - return x + y; - } -} diff --git a/component-model/src/language-support/csharp.md b/component-model/src/language-support/csharp.md index 0b46e685..175be144 100644 --- a/component-model/src/language-support/csharp.md +++ b/component-model/src/language-support/csharp.md @@ -38,11 +38,12 @@ cd adder Next, create or download the WIT world you would like to target. -For this example we will use the [`adder` world][adder-world], with an `add` function. +For this example we will use a WIT file containing two worlds +(we'll only use the `example` world at first). Copy and paste the following into a new file called "`wit/component.wit`". ```wit -{{#include ../../examples/tutorial/wit/adder/world.wit}} +{{#include ../../examples/tutorial/csharp/adder/world-hostapp.wit}} ``` In the `adder.csproj` project file, add a new `` @@ -50,7 +51,7 @@ at the same level as the existing ``: ```xml - + ``` @@ -68,8 +69,6 @@ And remove the automatically generated `Program.cs` file: rm Program.cs ``` -[adder-world]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/adder/world.wit - ## 3. Write the implementation for the `adder` world If you try to build the project with `dotnet build`, you'll get an error like the following: @@ -84,7 +83,7 @@ You are using a preview version of .NET. See: https://aka.ms/dotnet-support-poli Build failed with 1 error(s) in 34.6s ``` -This is because we've promised an implementation, but haven't yet written one for the `adder` world. +This is because we've promised an implementation, but haven't yet written one for the `example` world. To fix this, add the following code in a file called `Component.cs`: @@ -113,56 +112,6 @@ A successful run should show the following output [rust]: https://www.rust-lang.org/learn/get-started -## Building a component that exports an interface - -The previous example uses a WIT file that exports a function. -However, you'll often prefer to export an interface, -either to comply with an existing specification -or to capture a set of functions and types that tend to go together. -Let's expand our `example` world to export an interface rather than directly export the function. -We are also adding the `hostapp` world to our WIT file, -which we will implement in [the next section](#building-a-component-that-imports-an-interface) -to demonstrate how to build a component that *imports* an interface. - -Edit your `wit/component.wit` file to look like this: - -```wit -{{#include ../../examples/tutorial/csharp/adder/world-hostapp.wit}} -``` - -In our `Component.cs` example, we change the `namespace` declaration -to refer to the package name in the `wit/component.wit` file, -and change the `AddImpl` class so that it implements the `add` interface: - -```csharp -{{#include ../../examples/tutorial/csharp/adder/Component2.cs}} -``` - -You also need to edit your `adder.csproj` project file as follows, -to reflect that we are now implementing the `example` world: - -```diff -- -+ -``` - -Once again, compile an application to a Wasm component using `dotnet build`: - -```sh -$ dotnet build -Restore complete (0.4s) -You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy - adder succeeded (1.1s) → bin/Debug/net10.0/wasi-wasm/adder.dll - -Build succeeded in 2.5s -``` - -The component will be available at `bin/Debug/net10.0/wasi-wasm/native/adder.wasm`. - -If you peek at the bindings, you'll notice that we now implement a class for the `add` interface -rather than for the `example` world—this is a consistent pattern. -As you export more interfaces from your world, you implement more classes. - ## Building a component that imports an interface So far, we've been dealing with library components.