Módulos de Bindgen Bindings

O sistema de compilação dá suporte à geração de associações de bindgen por meio do tipo de módulo rust_bindgen . Bindgen fornece ligações Rust FFI para bibliotecas C (com algum suporte C++ limitado, que requer a configuração da propriedade cppstd ).

Uso básico de rust_bindgen

O que se segue é um exemplo de como definir um módulo que usa bindgen e como usar esse módulo como um engradado. Se você precisar usar ligações bindgen por meio de uma macro include!() , como para código externo, consulte a página Geradores de código-fonte.

Exemplo de biblioteca C para chamar de Rust

Segue um exemplo de biblioteca C que define uma estrutura e uma função para uso em Rust.

external/rust/libbuzz/libbuzz.h

typedef struct foo {
    int x;
} foo;

void fizz(int i, foo* cs);

external/rust/libbuzz/libbuzz.c

#include <stdio.h>
#include "libbuzz.h"

void fizz(int i, foo* my_foo){
    printf("hello from c! i = %i, my_foo->x = %i\n", i, my_foo->x);
}

Definindo um módulo rust_bindgen

Defina um cabeçalho de wrapper, external/rust/libbuzz/libbuzz_wrapper.h , que inclui todos os cabeçalhos relevantes:

// Include headers that are required for generating bindings in a wrapper header.
#include "libbuzz.h"

Defina o arquivo Android.bp como external/rust/libbuzz/Android.bp :

cc_library {
    name: "libbuzz",
    srcs: ["libbuzz.c"],
}

rust_bindgen {
     name: "libbuzz_bindgen",

     // Crate name that's used to generate the rust_library variants.
     crate_name: "buzz_bindgen",

     // Path to the wrapper source file.
     wrapper_src: "libbuzz_wrapper.h",

     // 'source_stem' controls the output filename.
     // This is the filename that's used in an include! macro.
     //
     // In this case, we just use "bindings", which produces
     // "bindings.rs".
     source_stem: "bindings",

     // Bindgen-specific flags and options to customize the bindings.
     // See the bindgen manual for more information.
     bindgen_flags: ["--verbose"],

     // Clang flags to be used when generating the bindings.
     cflags: ["-DSOME_FLAG"],

     // Shared, static, and header libraries which export the necessary
     // include directories must be specified.
     //
     // These libraries will also be included in the crate if static,
     // or propagated to dependents if shared.
     // static_libs: ["libbuzz"]
     // header_libs: ["libbuzz"]
     shared_libs: ["libbuzz"],
}

Para saber mais sobre o uso de sinalizadores de bindgen, consulte a seção do manual do bindgen em Personalizando vinculações geradas .

Se você usou esta seção para definir um módulo rust_bindgen como um pré-requisito para usar a macro include!() , retorne para Pré -requisito na página Geradores de código-fonte. Se não, continue com as próximas seções.

Usando ligações como uma caixa

Crie external/rust/hello_bindgen/Android.bp com o seguinte conteúdo:

rust_binary {
   name: "hello_bindgen",
   srcs: ["main.rs"],

   // Add the rust_bindgen module as if it were a rust_library dependency.
   rustlibs: ["libbuzz_bindgen"],
}

Crie external/rust/hello_bindgen/src/main.rs com o seguinte conteúdo:

//! Example crate for testing bindgen bindings

fn main() {
    let mut x = buzz_bindgen::foo { x: 2 };
    unsafe { buzz_bindgen::fizz(1, &mut x as *mut buzz_bindgen::foo) }
}

Finalmente, chame m hello_bindgen para construir o binário.

Testando ligações do Bindgen

As associações de Bindgen normalmente contêm vários testes de layout gerados para evitar incompatibilidades de layout de memória. O AOSP recomenda que você tenha um módulo de teste definido para esses testes e que os testes sejam executados como parte do conjunto de testes normal do seu projeto.

Um binário de teste para estes pode ser facilmente produzido definindo um módulo rust_test em external/rust/hello_bindgen/Android.bp :

rust_test {
    name: "bindings_test",
    srcs: [
        ":libbuzz_bindgen",
    ],
    crate_name: "buzz_bindings_test",
    test_suites: ["general-tests"],
    auto_gen_config: true,

    // Be sure to disable lints as the generated source
    // is not guaranteed to be lint-free.
    clippy_lints: "none",
    lints: "none",
}

Propriedades notáveis ​​de rust_bindgen

As propriedades definidas abaixo são adicionais às propriedades comuns importantes que se aplicam a todos os módulos. Eles são particularmente importantes para os módulos Rust bindgen ou exibem um comportamento exclusivo específico para o tipo de módulo rust_bindgen .

haste, nome, crate_name

rust_bindgen produz variantes de biblioteca, portanto, eles compartilham os mesmos requisitos com os módulos rust_library para as propriedades stem , name e crate_name . Consulte as propriedades da biblioteca Notable Rust para referência.

wrapper_src

Este é o caminho relativo para um arquivo de cabeçalho wrapper que inclui os cabeçalhos necessários para essas ligações. A extensão do arquivo determina como interpretar o cabeçalho e determina qual sinalizador -std usar por padrão. Supõe-se que seja um cabeçalho C, a menos que a extensão seja .hh ou .hpp . Se o seu cabeçalho C++ deve ter alguma outra extensão, defina a propriedade cpp_std para substituir o comportamento padrão que assume que o arquivo é um arquivo C.

fonte_haste

Este é o nome do arquivo de origem gerado . Este campo deve ser definido, mesmo se você estiver usando as ligações como uma grade, pois a propriedade stem controla apenas o nome do arquivo de saída para as variantes de biblioteca geradas. Se um módulo depende de vários geradores de origem (como bindgen e protobuf ) como origem em vez de caixas por meio de rustlibs , você deve garantir que todos os geradores de origem que são dependências desse módulo tenham valores source_stem exclusivos. Módulos dependentes copiam fontes de todas as dependências SourceProvider que são definidas em srcs para um diretório OUT_DIR comum, então colisões em source_stem resultariam em arquivos fonte gerados sendo sobrescritos no diretório OUT_DIR .

c_std

Esta é uma string que representa qual versão do padrão C usar. Os valores válidos estão listados abaixo:

  • Uma versão específica, como "gnu11"
    • O valor "experimental" definido pelo sistema de compilação em build/soong/cc/config/global.go , pode usar versões de rascunho como C++1z quando estiverem disponíveis.
    • "default" ou " " ambos usam o padrão do sistema de compilação.

Se estiver definido, a extensão do arquivo será ignorada e o cabeçalho será considerado um cabeçalho C. Isso não pode ser definido ao mesmo tempo que cpp_std .

cpp_std

cpp_std é uma string que representa qual versão padrão C usar. Valores válidos:

  • Uma versão específica, como "gnu++11"

    • O valor "experimental" definido pelo sistema de compilação em build/soong/cc/config/global.go , pode usar versões de rascunho como C++1z quando estiverem disponíveis.
    • "default" ou " " ambos o padrão do sistema de compilação.

Se isso for definido, a extensão do arquivo será ignorada e o cabeçalho será considerado um cabeçalho C++. Isso não pode ser definido ao mesmo tempo que c_std .

cflags

cflags fornece uma lista de strings de sinalizadores Clang necessários para interpretar corretamente os cabeçalhos.

custom_bindgen

Para casos de uso avançados, o bindgen pode ser usado como uma biblioteca, fornecendo uma API que pode ser manipulada como parte de um binário Rust personalizado. O campo custom_bindgen recebe o nome do módulo de um módulo rust_binary_host , que usa a API bindgen em vez do binário bindgen normal.

Este binário personalizado deve esperar argumentos de forma semelhante ao bindgen , como " my_bindgen [flags] wrapper_header.h -o [output\_path] -- [clang flags] ". A maior parte disso é tratada pela própria biblioteca bindgen . Para ver um exemplo desse uso, visite external/rust/crates/libsqlite3-sys/android/build.rs .

Além disso, o conjunto completo de propriedades da biblioteca está disponível para controlar a compilação da biblioteca, embora raramente precisem ser definidas ou alteradas.