简体   繁体   English

将 C# 项目编译到 WebAssembly

[英]Compiling C# project to WebAssembly

I need to compile a C# project to WebAssembly and be able to call some methods from JavaScript.我需要将 C# 项目编译到 WebAssembly 并能够从 JavaScript 调用一些方法。

I want to use it in an old ASP.NET MVC 4 application that needs to add some new features and I prefer to use C# instead JavaScript/TypeScript.我想在需要添加一些新功能的旧 ASP.NET MVC 4 应用程序中使用它,我更喜欢使用 C# 而不是 JavaScript/TypeScript。

Ideally I would like to compile to WebAssembly using.Net 6 but I can use any other alternative.理想情况下,我想使用.Net 6 编译为 WebAssembly,但我可以使用任何其他替代方法。

I'm running.Net 6 on Windows 10 Version 21H1 (OS Build 19043.1415)我在 Windows 10 版本 21H1(OS Build 19043.1415)上运行.Net 6

I've installed:我已经安装了:

  • Visual Studio 2022视觉工作室 2022
  • the workload "wasm-tools" (.NET WebAssembly build tools)工作负载“wasm-tools”(.NET WebAssembly 构建工具)

But every time I search for a tutorial, example, etc, about how to use the .NET WebAssembly build tools the results are about Blazor.但是每次我搜索关于如何使用 .NET WebAssembly 构建工具的教程、示例等时,结果都是关于 Blazor。

I've read this tutorial but I can't find the mono-wasm compiler (and like I said above I would like to use.Net 6 to compile whenever possible.)我已经阅读了本教程,但找不到 mono-wasm 编译器(就像我上面所说的,我想尽可能使用 .Net 6 进行编译。)

Can anyone please help me with this?谁能帮我解决这个问题?

Thank you.谢谢你。

There is the experimental NativeAOT-LLVM ( https://github.com/dotnet/runtimelab/tree/feature/NativeAOT-LLVM ).有实验性的 NativeAOT-LLVM ( https://github.com/dotnet/runtimelab/tree/feature/NativeAOT-LLVM )。 It is not an official Microsoft WebAssembly compiler, its supported by the community, but.Net 6 is available.它不是官方的 Microsoft WebAssembly 编译器,受社区支持,但 .Net 6 可用。 First, and this only works on Windows, you need to install and activate emscripten.首先,这仅适用于 Windows,您需要安装并激活 emscripten。 I wont cover installing emscripten here, but you can read https://emscripten.org/docs/getting_started/downloads.html .我不会在这里介绍安装 emscripten,但您可以阅读https://emscripten.org/docs/getting_started/downloads.html

To create and run a dotnet c# library:要创建和运行 dotnet c# 库:

  1. Create the library project:创建库项目:
dotnet new classlib
  1. Create the library code, we'll use something simple that avoids any problems marshalling things like javascript strings, so in the Class1.cs file add创建库代码,我们将使用一些简单的方法来避免编组 javascript 字符串之类的任何问题,因此在Class1.cs文件中添加
    [System.Runtime.InteropServices.UnmanagedCallersOnly(EntryPoint = "Answer")]
    public static int Answer()
    {
        return 41;
    }

This will create a function, Answer that can be called from outside managed code, ie from Javascript这将创建一个 function,可以从外部托管代码调用的Answer ,即从 Javascript

  1. Add a nuget.config添加 nuget.config
 dotnet new nugetconfig
  1. In the nuget.config add the reference to allow the experimental package to be downloaded.在 nuget.config 添加引用以允许下载实验 package。 You can also change the package download location to avoid it adding experimental packages to your global nuget location.您还可以更改 package 下载位置,以避免将实验包添加到您的全局 nuget 位置。 Your nuget.config should look like:您的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. Add the package references for the compiler to your project's csproj file so that it ends with this:将编译器的 package 引用添加到项目的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. Publish your project to wasm:将您的项目发布到 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

This will build the project referencing the browser-wasm runtime.这将构建引用 browser-wasm 运行时的项目。 MSBuildEnableWorkloadResolver stops the build process checking for Mono's wasm-tools Visual Studio workload which we are not using here. MSBuildEnableWorkloadResolver停止构建过程检查 Mono 的 wasm-tools Visual Studio 工作负载,我们在这里没有使用。 (Mono is a different compiler and runtime, which I believe is getting similar support for .net 7). (Mono 是一个不同的编译器和运行时,我相信它正在获得对 .net 7 的类似支持)。 EmccExtraArgs allows us to add parameters to emscripten's emcc and we need that to export the two function we will call from Javascript: Answer - this is our library function, and CoreRT_StaticInitialization this is called once per lifetime of the wasm module to initialize the runtime. EmccExtraArgs allows us to add parameters to emscripten's emcc and we need that to export the two function we will call from Javascript: Answer - this is our library function, and CoreRT_StaticInitialization this is called once per lifetime of the wasm module to initialize the runtime. Note the additional underscores in front of the names.请注意名称前面的附加下划线。 The compilation takes a while, but when finished you should have a subfolder bin\x64\Debug\net6.0\browser-wasm\native where you will find the wasm, some html, and some javascript.编译需要一段时间,但完成后,您应该有一个子文件夹bin\x64\Debug\net6.0\browser-wasm\native ,您可以在其中找到 wasm、一些 html 和一些 javascript。 In the html file at the end, before the closing body tag, initialize the runtime and call your function with:在最后的 html 文件中,在结束body标记之前,初始化运行时并使用以下命令调用您的 function:

    <script>
      Module.onRuntimeInitialized = _ => {
        const corertInit = Module.cwrap('CoreRT_StaticInitialization', 'number', []);
        corertInit();

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

Then server that up with the web server of your choosing, browse to the page and check the console where if everything has gone to plan, and the stars align (this is experimental), you should see然后将其与您选择的 web 服务器一起服务器,浏览到页面并检查控制台,如果一切都按计划进行,并且星星对齐(这是实验性的),您应该看到在此处输入图像描述

I recently came across: https://github.com/Elringus/DotNetJS我最近遇到: https://github.com/Elringus/DotNetJS

Looks very interesting and closer to how I would want to use c# in the web browser.看起来非常有趣,并且更接近我想要在 web 浏览器中使用 c# 的方式。 I will be looking at this in the next few months我会在接下来的几个月里看看这个

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM