Módulos de enlaces Bindgen

El sistema de compilación admite la generación de enlaces bindgen a través del tipo de módulo rust_bindgen . Bindgen proporciona enlaces de Rust FFI a bibliotecas C (con algo de compatibilidad limitada con C++, lo que requiere configurar la propiedad cppstd ).

Uso básico de rust_bindgen

Lo que sigue es un ejemplo de cómo definir un módulo que usa bindgen y cómo usar ese módulo como caja. Si necesita usar enlaces bindgen a través de una macro include!() , como para código externo, consulte la página Generadores de código fuente.

Ejemplo de biblioteca C para llamar desde Rust

A continuación, se muestra una biblioteca C de ejemplo que define una estructura y una función para usar en 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);
}

Definición de un módulo rust_bindgen

Defina un encabezado contenedor, external/rust/libbuzz/libbuzz_wrapper.h , que incluye todos los encabezados relevantes:

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

Defina el archivo 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 obtener más información sobre el uso de indicadores de bindgen, consulte la sección del manual de bindgen sobre cómo personalizar los enlaces generados .

Si usó esta sección para definir un módulo rust_bindgen como requisito previo para usar la macro include!() , vuelva a Prerrequisito en la página Generadores de código fuente. Si no, continúe con las siguientes secciones.

Usar ataduras como una caja

Cree external/rust/hello_bindgen/Android.bp con el siguiente contenido:

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

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

Cree external/rust/hello_bindgen/src/main.rs con el siguiente contenido:

//! 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, llama a m hello_bindgen para construir el binario.

Prueba de enlaces de Bindgen

Los enlaces de Bindgen suelen contener una serie de pruebas de diseño generadas para evitar discrepancias en el diseño de la memoria. AOSP recomienda que tenga un módulo de prueba definido para estas pruebas y que las pruebas se ejecuten como parte del conjunto de pruebas normal de su proyecto.

Se puede producir fácilmente un binario de prueba para estos mediante la definición de un módulo rust_test en 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",
}

Propiedades notables de rust_bindgen

Las propiedades definidas a continuación se suman a las propiedades comunes importantes que se aplican a todos los módulos. Estos son particularmente importantes para los módulos de Rust bindgen o exhiben un comportamiento único específico para el tipo de módulo rust_bindgen .

vástago, nombre, crate_name

rust_bindgen produce variantes de biblioteca, por lo que comparten los mismos requisitos con los módulos rust_library para las propiedades stem , name y crate_name . Consulte Propiedades notables de la biblioteca de Rust como referencia.

wrapper_src

Esta es la ruta relativa a un archivo de encabezado contenedor que incluye los encabezados necesarios para estos enlaces. La extensión del archivo determina cómo interpretar el encabezado y determina qué indicador -std usar de manera predeterminada. Se supone que es un encabezado C a menos que la extensión sea .hh o .hpp . Si su encabezado C++ debe tener alguna otra extensión, configure la propiedad cpp_std para anular el comportamiento predeterminado que supone que el archivo es un archivo C.

source_stem

Este es el nombre de archivo para el archivo fuente generado . Este campo debe definirse, incluso si está utilizando los enlaces como una caja, ya que la propiedad stem solo controla el nombre del archivo de salida para las variantes de biblioteca generadas. Si un módulo depende de varios generadores de fuentes (como bindgen y protobuf ) como fuente en lugar de cajas a través de rustlibs , debe asegurarse de que todos los generadores de fuentes que son dependencias de ese módulo tengan valores source_stem únicos. Los módulos dependientes copian fuentes de todas las dependencias de SourceProvider que están definidas en srcs a un directorio OUT_DIR común, por lo que las colisiones en source_stem darían como resultado que los archivos fuente generados se sobrescriban en el directorio OUT_DIR .

c_std

Esta es una cadena que representa qué versión estándar de C usar. Los valores válidos se enumeran a continuación:

  • Una versión específica, como "gnu11"
    • El valor "experimental" definido por el sistema de compilación en build/soong/cc/config/global.go , puede usar versiones preliminares como C++1z cuando estén disponibles.
    • "predeterminado" o " " ambos usan el sistema de compilación predeterminado.

Si se configura, la extensión del archivo se ignora y se asume que el encabezado es un encabezado C. Esto no se puede establecer al mismo tiempo que cpp_std .

cpp_std

cpp_std es una cadena que representa qué versión estándar de C usar. Valores válidos:

  • Una versión específica, como "gnu++11"

    • El valor "experimental" definido por el sistema de compilación en build/soong/cc/config/global.go , puede usar versiones preliminares como C++1z cuando estén disponibles.
    • "predeterminado" o " " ambos son el sistema de compilación predeterminado.

Si se configura, la extensión del archivo se ignora y se supone que el encabezado es un encabezado de C++. Esto no se puede configurar al mismo tiempo que c_std .

banderas

cflags proporciona una lista de cadenas de indicadores Clang necesarios para interpretar correctamente los encabezados.

custom_bindgen

Para casos de uso avanzado, bindgen se puede usar como una biblioteca, proporcionando una API que se puede manipular como parte de un binario de Rust personalizado. El campo custom_bindgen toma el nombre del módulo de un módulo rust_binary_host , que utiliza la API bindgen en lugar del binario bindgen normal.

Este binario personalizado debe esperar argumentos de forma similar a bindgen , como " my_bindgen [flags] wrapper_header.h -o [output\_path] -- [clang flags] ". La mayor parte de esto es manejado por la propia biblioteca bindgen . Para ver un ejemplo de este uso, visite external/rust/crates/libsqlite3-sys/android/build.rs .

Además, el conjunto completo de propiedades de la biblioteca está disponible para controlar la compilación de la biblioteca, aunque rara vez es necesario definirlas o cambiarlas.