Learning WASM #3

Rustでライブラリを作成して、dotnetからそれを呼び出すのを試した。
https://github.com/iwate/learn-wasm-with-dotnet/tree/main/challenge02

まずは、簡単なとこから、ただの2値の足し算をするadd関数をrust -> wasm -> dotnetで実行する

rust + wasm で検索したら、wasm-packばっかりで、なかなかただのwasmの生成方法がわからなかったけど、wasiとかwasmtimeでググったら何とか知見が得られた。

まずは、rustでwasmをターゲットにしてコンパイルできるように、ターゲットを足す。

rustup target add wasm32-unknown-unknown

次に、普通にrustのプロジェクトを作る。add関数を外から使いたいからプロジェクトタイプはlibで。

Cargo.tomlはこんな感じでまっさらでいい。

[package]
name = "challenge02"
version = "0.1.0"
authors = ["iwate <github@iwate.me>"]
edition = "2018"

[dependencies]

wasmにするために唯一やらなくちゃいけないことは#[no_mangle]をつけるってこと。こういうのrustだとなんていうんだろ?dotnet的にattributeって言うのかな?それともjavaみたいにannotation?

#[no_mangle]
fn add(a: i32, b: i32) -> i32 {
    return a + b;
}

調べた。 attributeらしい。#がouter attributeで#!がinnter attributeだって。
https://doc.rust-lang.org/book/appendix-02-operators.html

あとは、ビルドするときにターゲットを指定する。 releaseビルドにしないと、wasmがデバッグ用のコードか何かですごく膨らむ。

cargo build --target=wasm32-unknown-unknown --release

あとは生成されたwasmをdotnetから使うだけ。

using System;
using Wasmtime;

using var engine = new Engine();
using var module = Module.FromFile(engine, "challenge02.wasm");
using var host = new Host(engine);

using dynamic instance = host.Instantiate(module);
var result = instance.add(1, 2);

Console.WriteLine(result);

コンパイルが面倒なので、ビルドイベントでrustのビルドとwasmのコピーもしちゃう。

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
        <Nullable>enable</Nullable>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Wasmtime" Version="0.27.0-preview1" />
    </ItemGroup>

    <ItemGroup>
      <None Update="challenge02.wasm">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </None>
    </ItemGroup>

    <Target Name="RustBuild" BeforeTargets="Build">
        <Exec WorkingDirectory="../rust" Command="cargo build --target=wasm32-unknown-unknown --release" />
        <Copy SourceFiles="../rust/target/wasm32-unknown-unknown/release/challenge02.wasm" DestinationFiles="./challenge02.wasm" />
    </Target>

</Project>

基本はできたので、次はwasm + protocol bufferを返してdotnetからrustを呼び出すコードを書く。


You'll only receive email when they publish something new.

More from iwate