【问题标题】:Compiling C# project to WebAssembly将 C# 项目编译为 WebAssembly
【发布时间】:2022-01-25 04:42:56
【问题描述】:

我需要将 C# 项目编译为 WebAssembly 并能够从 JavaScript 调用一些方法。

我想在需要添加一些新功能的旧 ASP.NET MVC 4 应用程序中使用它,并且我更喜欢使用 C# 而不是 JavaScript/TypeScript。

理想情况下,我想使用 .Net 6 编译为 WebAssembly,但我可以使用任何其他替代方案。

我在 Windows 10 版本 21H1(操作系统内部版本 19043.1415)上运行 .Net 6

我已经安装了:

  • Visual Studio 2022
  • 工作负载“wasm-tools”(.NET WebAssembly 构建工具)

但每次我搜索有关如何使用 .NET WebAssembly 构建工具的教程、示例等时,结果都是关于 Blazor。

我已阅读 this tutorial,但找不到 mono-wasm 编译器(就像我上面所说的,我想尽可能使用 .Net 6 进行编译。)

谁能帮我解决这个问题?

谢谢。

【问题讨论】:

    标签: c# webassembly .net-6.0


    【解决方案1】:

    有实验性的 NativeAOT-LLVM (https://github.com/dotnet/runtimelab/tree/feature/NativeAOT-LLVM)。它不是官方的 Microsoft WebAssembly 编译器,受社区支持,但 .Net 6 可用。首先,这仅适用于 Windows,您需要安装并激活 emscripten。我不会在这里介绍如何安装 emscripten,但你可以阅读 https://emscripten.org/docs/getting_started/downloads.html。

    创建和运行 dotnet c# 库:

    1. 创建库项目:
    dotnet new classlib
    
    1. 创建库代码,我们将使用一些简单的方法来避免编组 javascript 字符串之类的任何问题,因此在 Class1.cs 文件中添加
        [System.Runtime.InteropServices.UnmanagedCallersOnly(EntryPoint = "Answer")]
        public static int Answer()
        {
            return 41;
        }
    

    这将创建一个函数,Answer,可以从外部托管代码(即 Javascript)调用

    1. 添加 nuget.config
     dotnet new nugetconfig
    
    1. 在 nuget.config 中添加引用以允许下载实验包。您还可以更改包下载位置,以避免将实验包添加到您的全局 nuget 位置。您的 nuget.config 应如下所示:
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <config>
        <add key="globalPackagesFolder" value=".packages" />
      </config>
      <packageSources>
        <!--To inherit the global NuGet package sources remove the <clear/> line below -->
        <clear />
        <add key="dotnet-experimental" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json" />
        <add key="nuget" value="https://api.nuget.org/v3/index.json" />
      </packageSources>
    </configuration>
    
    1. 将编译器的包引用添加到项目的csproj 文件中,使其以此结尾:
      <ItemGroup>
        <PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM" Version="7.0.0-*" />
        <PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler.LLVM" Version="7.0.0-*" />
      </ItemGroup>
    
    </Project>
    
    1. 将您的项目发布到 wasm:
    dotnet publish /p:NativeLib=Static /p:SelfContained=true -r browser-wasm -c Debug /p:TargetArchitecture=wasm /p:PlatformTarget=AnyCPU /p:MSBuildEnableWorkloadResolver=false /p:EmccExtraArgs="-s EXPORTED_FUNCTIONS=_Answer%2C_CoreRT_StaticInitialization -s EXPORTED_RUNTIME_METHODS=cwrap" --self-contained
    

    这将构建引用 browser-wasm 运行时的项目。 MSBuildEnableWorkloadResolver 停止构建过程检查 Mono 的 wasm-tools Visual Studio 工作负载,我们在这里没有使用。 (Mono 是一个不同的编译器和运行时,我相信它正在获得对 .net 7 的类似支持)。 EmccExtraArgs 允许我们向 emscripten 的 emcc 添加参数,并且我们需要它来导出我们将从 Javascript 调用的两个函数:Answer - 这是我们的库函数,CoreRT_StaticInitialization 这是在每个生命周期调用一次wasm 模块来初始化运行时。请注意名称前面的附加下划线。编译需要一段时间,但完成后您应该有一个子文件夹bin\x64\Debug\net6.0\browser-wasm\native,您可以在其中找到 wasm、一些 html 和一些 javascript。在最后的 html 文件中,在关闭 body 标记之前,初始化运行时并调用您的函数:

        <script>
          Module.onRuntimeInitialized = _ => {
            const corertInit = Module.cwrap('CoreRT_StaticInitialization', 'number', []);
            corertInit();
    
            const answer = Module.cwrap('Answer', 'number', []);
            console.log(answer());
          };
        </script>
    

    然后将其与您选择的网络服务器一起服务器,浏览到页面并检查控制台,如果一切都按计划进行,并且星星对齐(这是实验性的),您应该会看到

    【讨论】:

      猜你喜欢
      • 2020-04-28
      • 1970-01-01
      • 1970-01-01
      • 2017-11-29
      • 2018-03-16
      • 2017-12-22
      • 1970-01-01
      • 2019-08-24
      • 1970-01-01
      相关资源
      最近更新 更多