Dependencias nativas de Blazor WebAssembly de ASP.NET Core

Las aplicaciones Blazor WebAssembly pueden usar dependencias nativas compiladas para ejecutarse en WebAssembly. Puede vincular estáticamente dependencias nativas en el entorno de ejecución de WebAssembly de .NET mediante las herramientas de compilación de WebAssembly de .NET, las mismas herramientas que se usan para compilar con antelación una aplicación Blazor para WebAssembly o para volver a vincular el entorno de ejecución para quitar las características no utilizadas.

Este artículo solo se aplica a Blazor WebAssembly.

Herramientas de compilación de WebAssembly de .NET

Las herramientas de compilación de WebAssembly de .NET se basan en Emscripten, una cadena de herramientas del compilador para la plataforma web. Para instalar las herramientas de compilación de WebAssembly de .NET, use cualquiera de los enfoques siguientes:

  • Para la carga de trabajo de ASP.NET y desarrollo web en el instalador de Visual Studio, seleccione la opción Herramientas de compilación de WebAssembly de .NET en la lista de componentes opcionales.
  • Ejecute dotnet workload install wasm-tools en un shell de comandos.

Agregue dependencias nativas a una aplicación de Blazor WebAssembly mediante la adición de elementos NativeFileReference en el archivo del proyecto de la aplicación. Cuando se compila el proyecto, las herramientas de compilación de WebAssembly de .NET pasan cada NativeFileReference a Emscripten para que se compilen y vinculen al entorno de ejecución. A continuación, inserte p/invoke en el código nativo del código .NET de la aplicación.

Por lo general, cualquier código nativo portable se puede usar como dependencia nativa con Blazor WebAssembly. Puede agregar dependencias nativas al código C/C++ o al código compilado previamente mediante Emscripten:

  • Archivos objeto (.o)
  • Archivos de almacenamiento (.a)
  • Bitcode (.bc)
  • Módulos de WebAssembly independientes (.wasm)

Normalmente, las dependencias precompiladas deben compilarse con la misma versión de Emscripten que se usa para compilar el entorno de ejecución de WebAssembly de .NET.

Nota

Para las propiedades y destinos de MSBuild de Mono/WebAssembly, consulte WasmApp.targets (repositorio dotnet/runtime GitHub). La documentación oficial de las propiedades MSBuild comunes está planeada según las opciones de configuración de msbuild de Blazor del documento (dotnet/docs n.º 27395).

Uso de código nativo

Agregue una función de C nativa simple a una aplicación Blazor WebAssembly:

  1. Cree un proyecto de Blazor WebAssembly .

  2. Agregue un archivo Test.c al proyecto.

  3. Agregue una función de C para calcular factoriales.

    Test.c:

    int fact(int n)
    {
        if (n == 0) return 1;
        return n * fact(n - 1);
    }
    
  4. Agregue NativeFileReference para Test.c en el archivo del proyecto de la aplicación:

    <ItemGroup>
      <NativeFileReference Include="Test.c" />
    </ItemGroup>
    
  5. En un componente de Razor agregue DllImportAttribute para la función fact en la biblioteca Test generada y llame al método fact a partir del código de .NET en el componente.

    Pages/NativeCTest.razor:

    @page "/native-c-test"
    @using System.Runtime.InteropServices
    
    <PageTitle>Native C</PageTitle>
    
    <h1>Native C Test</h1>
    
    <p>
        @@fact(3) result: @fact(3)
    </p>
    
    @code {
        [DllImport("Test")]
        static extern int fact(int n);
    }
    

Al compilar la aplicación con las herramientas de compilación de WebAssembly de .NET instaladas, el código C nativo se compila y vincula al entorno de ejecución de WebAssembly de .NET (dotnet.wasm). Una vez compilada la aplicación, ejecútela para ver el valor factorial representado.

Devoluciones de llamada de método administrado de C++

Etiquete los métodos administrados que se pasan a C++ con el atributo [UnmanagedCallersOnly].

El método marcado con el atributo [UnmanagedCallersOnly] deben ser static. Para llamar a un método de instancia en un componente Razor, pase un GCHandle para la instancia a C++ y, a continuación, vuelva a pasarlo a nativo. Como alternativa, use algún otro método para identificar la instancia del componente.

El método marcado con [DllImport] debe usar un puntero de función de C# 9.0 en lugar de un tipo delegado para el argumento de devolución de llamada.

Nota

Para los tipos de puntero de función de C# en los métodos [DllImport], use IntPtr en la firma del método en el lado administrado en lugar de delegate *unmanaged<int, void>. Para obtener más información, consulte Devolución de llamada [WASM] desde código nativo a .NET: No se admite el análisis de tipos de puntero de función en firmas (dotnet/runtime n.º 56145).

Empaquetado de dependencias nativas en un paquete NuGet

Los paquetes NuGet pueden contener dependencias nativas para su uso en WebAssembly. Estas bibliotecas y su funcionalidad nativa están disponibles para cualquier aplicación Blazor WebAssembly. Los archivos de las dependencias nativas deben compilarse para WebAssembly y empaquetarse en la browser-wasmcarpeta específica de la arquitectura. No se hace referencia automáticamente a las dependencias específicas de WebAssembly y se debe hacer referencia a ellas manualmente como NativeFileReference. Los autores de paquetes pueden optar por agregar las referencias nativas incluyendo un archivo .props en el paquete con las referencias.

Uso de la biblioteca de ejemplo SkiaSharp

SkiaSharp es una biblioteca de gráficos 2D multiplataforma para .NET basada en la biblioteca de gráficos Skia nativa con compatibilidad con Blazor WebAssembly.

Para usar SkiaSharp en una aplicación Blazor WebAssembly:

  1. Agregue una referencia de paquete al paquete SkiaSharp.Views.Blazor en un proyecto Blazor WebAssembly. Use el proceso de Visual Studio para agregar paquetes a una aplicación (Administrar paquetes NuGet) con la opción Incluir versión preliminar seleccionada o ejecute el comando dotnet add package en un shell de comandos:

    dotnet add package –-prerelease SkiaSharp.Views.Blazor
    

    Nota

    Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.

  2. Agregue un componente SKCanvasView a la aplicación con lo siguiente:

    • Espacios de nombres SkiaSharp y SkiaSharp.Views.Blazor.
    • Lógica que se trazará en el componente de vista de lienzo de SkiaSharp (SKCanvasView).

    Pages/NativeDependencyExample.razor:

    @page "/native-dependency-example"
    @using SkiaSharp
    @using SkiaSharp.Views.Blazor
    
    <PageTitle>Native dependency</PageTitle>
    
    <h1>Native dependency example with SkiaSharp</h1>
    
    <SKCanvasView OnPaintSurface="@OnPaintSurface" />
    
    @code {
        private void OnPaintSurface(SKPaintSurfaceEventArgs e)
        {
            var canvas = e.Surface.Canvas;
    
            canvas.Clear(SKColors.White);
    
            using var paint = new SKPaint
            {
                Color = SKColors.Black,
                IsAntialias = true,
                TextSize = 24
            };
    
            canvas.DrawText("SkiaSharp", 0, 24, paint);
        }
    }
    
  3. Compile la aplicación; esta operación puede tardar varios minutos. Ejecute la aplicación y vaya al componente NativeDependencyExample en /native-dependency-example.