Dependências nativas do ASP.NET Core Blazor WebAssembly

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Os aplicativos Blazor WebAssembly podem usar dependências nativas criadas para serem executadas no WebAssembly. Você pode vincular estaticamente dependências nativas ao runtime do .NET WebAssembly usando as Ferramentas de build do .NET WebAssembly, as mesmas ferramentas usadas para compilação AOT (ahead-of-time) um Blazor aplicativo para o WebAssembly e para revincular o runtime para remover recursos não utilizados.

Este artigo só se aplica a Blazor WebAssembly.

Ferramentas de build do .NET WebAssembly

As ferramentas de build do .NET WebAssembly são baseadas no Emscripten, uma cadeia de ferramentas do compilador para a plataforma Web. Para obter mais informações sobre as ferramentas de compilação, incluindo a instalação, confira Ferramentas de criação e compilação antecipada (AOT) do Blazor WebAssembly no ASP.NET Core.

Adicione dependências nativas a um aplicativo Blazor WebAssembly adicionando itens NativeFileReference no arquivo de projeto do aplicativo. Quando o projeto é criado, cada NativeFileReference é passado para o Emscripten pelas ferramentas de build do .NET WebAssembly para que eles sejam compilados e vinculados ao runtime. Em seguida, p/invoke no código nativo do código .NET do aplicativo.

Em geral, qualquer código nativo portátil pode ser usado como uma dependência nativa com Blazor WebAssembly. Você pode adicionar dependências nativas ao código C/C++ ou código compilado anteriormente usando o Emscripten:

  • Arquivos-objetos (.o)
  • Arquivamento (.a)
  • Bitcode (.bc)
  • Módulos WebAssembly autônomos (.wasm)

As dependências predefinidas normalmente devem ser criadas usando a mesma versão do Emscripten usada para criar o runtime do .NET WebAssembly.

Observação

Para propriedades e destinos do MSBuild Mono/WebAssembly, confira WasmApp.targets (repositório do GitHub dotnet/runtime). A documentação oficial para propriedades comuns do MSBuild é planejada de acordo com as opções de configuração do documento do MSBuild do Blazor (dotnet/docs #27395).

Usar código nativo

Adicione uma função C nativa simples a um aplicativo Blazor WebAssembly:

  1. Crie um novo projeto Blazor WebAssembly.

  2. Adicione o arquivo Test.c ao projeto.

  3. Adicione uma função C para fatoriais de computação.

    Test.c:

    int fact(int n)
    {
        if (n == 0) return 1;
        return n * fact(n - 1);
    }
    
  4. Adicione um NativeFileReference para Test.c no arquivo de projeto do aplicativo:

    <ItemGroup>
      <NativeFileReference Include="Test.c" />
    </ItemGroup>
    
  5. Em um componente Razor, adicione um DllImportAttribute para a função fact na biblioteca Test gerada e chame o método fact do código .NET no 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);
    }
    

Quando você cria o aplicativo com as ferramentas de build do .NET WebAssembly instaladas, o código C nativo é compilado e vinculado ao runtime do .NET WebAssembly (dotnet.wasm). Depois que o aplicativo for criado, execute-o para ver o valor fatorial renderizado.

Retornos de chamada de método gerenciado do C++

Rotular métodos gerenciados que são passados para C++ com o atributo [UnmanagedCallersOnly].

O método marcado com o atributo [UnmanagedCallersOnly] deve ser static. Para chamar um método de instância em um componente Razor, passe um GCHandle para a instância para C++ e, em seguida, passe-o de volta para nativo. Como alternativa, use outro método para identificar a instância do componente.

O método marcado com [DllImport] deve usar um ponteiro de função C# 9.0 em vez de um tipo delegado para o argumento de retorno de chamada.

Observação

Para tipos de ponteiro de função C# em métodos [DllImport], use IntPtr na assinatura do método no lado gerenciado em vez de delegate *unmanaged<int, void>. Para obter mais informações, confira Retorno de chamada [WASM] do código nativo para o .NET: não há suporte para tipos de ponteiro de função de análise em assinaturas (dotnet/runtime #56145).

Dependências nativas em um pacote NuGet

Os pacotes NuGet podem conter dependências nativas para uso no WebAssembly. Essas bibliotecas e suas funcionalidades nativas estão disponíveis para qualquer aplicativo Blazor WebAssembly. Os arquivos para as dependências nativas devem ser criados para WebAssembly e empacotados na browser-wasmpasta específica da arquitetura. As dependências específicas do WebAssembly não são referenciadas automaticamente e devem ser referenciadas manualmente como NativeFileReferences. Os autores de pacote podem optar por adicionar as referências nativas incluindo um arquivo .props no pacote com as referências.

Uso da biblioteca de exemplos do SkiaSharp

SkiaSharp é uma biblioteca de elementos gráficos 2D multiplataforma para .NET com base na biblioteca de elementos gráficos do Skia nativa com suporte para Blazor WebAssembly.

Para usar o SkiaSharp em um aplicativo Blazor WebAssembly:

  1. Adicione uma referência de pacote ao pacote SkiaSharp.Views.Blazor em um projeto Blazor WebAssembly. Use o processo do Visual Studio para adicionar pacotes a um aplicativo (Gerenciar Pacotes NuGet com Incluir pré-lançamento selecionado) ou execute o comando dotnet add package em um shell de comando:

    dotnet add package –-prerelease SkiaSharp.Views.Blazor
    

    Observação

    Para obter diretrizes sobre como adicionar pacotes a aplicativos .NET, consulte os artigos em Instalar e gerenciar pacotes no Fluxo de trabalho de consumo de pacotes (documentação do NuGet). Confirme as versões corretas de pacote em NuGet.org.

  2. Adicione um componente SKCanvasView ao aplicativo com o seguinte:

    • Namespaces SkiaSharp e SkiaSharp.Views.Blazor.
    • Lógica para desenhar no componente Exibição de Tela do 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. Crie o aplicativo, o que pode levar vários minutos. Execute o aplicativo e navegue para a componente NativeDependencyExample em /native-dependency-example.

Recursos adicionais

Ferramentas de build do .NET WebAssembly