Модули Bindgen Bindings

Система сборки поддерживает создание привязок bindgen через тип модуля rust_bindgen . Bindgen предоставляет привязки Rust FFI к библиотекам C (с некоторой ограниченной поддержкой C++, которая требует установки свойства cppstd ).

Базовое использование rust_bindgen

Далее следует пример того, как определить модуль, использующий bindgen, и как использовать этот модуль в качестве крейта. Если вам нужно использовать привязки bindgen через макрос include!() , например, для внешнего кода, см. страницу Генераторы исходного кода .

Пример библиотеки C для вызова из Rust

Ниже приведен пример библиотеки C, которая определяет структуру и функцию для использования в 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);
}

Определение модуля rust_bindgen

Определите заголовок оболочки external/rust/libbuzz/libbuzz_wrapper.h , который включает все соответствующие заголовки:

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

Определите файл Android.bp как 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"],
}

Чтобы узнать больше об использовании флагов bindgen, см. раздел руководства по bindgen, посвященный настройке сгенерированных привязок.

Если вы использовали этот раздел для определения модуля rust_bindgen в качестве предварительного условия для использования макроса include!() , вернитесь к Предварительным требованиям на странице Генераторы исходного кода. Если нет, переходите к следующим разделам.

Использование креплений в качестве ящика

Создайте external/rust/hello_bindgen/Android.bp со следующим содержимым:

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

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

Создайте external/rust/hello_bindgen/src/main.rs со следующим содержимым:

//! 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) }
}

Наконец, вызовите m hello_bindgen , чтобы построить двоичный файл.

Тестирование привязок Bindgen

Привязки Bindgen обычно содержат ряд сгенерированных тестов макета для предотвращения несоответствия макета памяти. AOSP рекомендует, чтобы у вас был тестовый модуль, определенный для этих тестов, и чтобы эти тесты выполнялись как часть обычного набора тестов вашего проекта.

Для них можно легко создать тестовый двоичный файл, определив модуль rust_test в файле 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",
}

Известные свойства rust_bindgen

Определенные ниже свойства являются дополнением к важным общим свойствам , которые применяются ко всем модулям. Они либо особенно важны для модулей Rust bindgen, либо демонстрируют уникальное поведение, специфичное для типа модуля rust_bindgen .

ствол, имя, crate_name

rust_bindgen создает варианты библиотек, поэтому они имеют те же требования, что и модули rust_library , для свойств stem , name и crate_name . Для справки см. Известные свойства библиотеки Rust .

wrapper_src

Это относительный путь к файлу заголовка оболочки, который включает заголовки, необходимые для этих привязок. Расширение файла определяет, как интерпретировать заголовок, и определяет, какой флаг -std использовать по умолчанию. Предполагается, что это заголовок C, если только расширение не .hh или .hpp . Если ваш заголовок C++ должен иметь другое расширение, установите свойство cpp_std , чтобы переопределить поведение по умолчанию, которое предполагает, что файл является файлом C.

source_stem

Это имя файла для сгенерированного исходного файла . Это поле должно быть определено, даже если вы используете привязки в качестве ящика, поскольку свойство stem управляет только именем выходного файла для сгенерированных вариантов библиотеки. Если модуль зависит от нескольких генераторов исходного кода (таких как bindgen и protobuf ) как источник, а не как крейты через rustlibs , вы должны убедиться, что все генераторы исходного кода, являющиеся зависимостями этого модуля, имеют уникальные значения source_stem . Зависимые модули копируют исходники из всех зависимостей SourceProvider , определенных в srcs , в общий каталог OUT_DIR , поэтому коллизии в source_stem приведут к перезаписи сгенерированных исходных файлов в каталоге OUT_DIR .

c_std

Это строка, представляющая, какую версию стандарта C использовать. Допустимые значения перечислены ниже:

  • Конкретная версия, например "gnu11"
    • «экспериментальное» значение, определенное системой сборки в build/soong/cc/config/global.go , может использовать черновые версии, такие как C++1z , когда они доступны.
    • "default" или " " оба используют систему сборки по умолчанию.

Если это установлено, расширение файла игнорируется, и предполагается, что заголовок является заголовком C. Его нельзя установить одновременно с cpp_std .

cpp_std

cpp_std — это строка, указывающая, какую версию стандарта C использовать. Допустимые значения:

  • Конкретная версия, например "gnu++11"

    • «экспериментальное» значение, определенное системой сборки в build/soong/cc/config/global.go , может использовать черновые версии, такие как C++1z , когда они доступны.
    • "по умолчанию" или " " по умолчанию для системы сборки.

Если это установлено, расширение файла игнорируется, и предполагается, что заголовок является заголовком C++. Это не может быть установлено одновременно с c_std .

cflags

cflags предоставляет строковый список флагов Clang, необходимых для правильной интерпретации заголовков.

custom_bindgen

Для расширенных вариантов использования bindgen можно использовать как библиотеку, предоставляющую API, которым можно манипулировать как частью пользовательского бинарного файла Rust. Поле custom_bindgen принимает имя модуля rust_binary_host , который использует API bindgen вместо обычного двоичного bindgen .

Этот пользовательский двоичный файл должен ожидать аргументы, аналогичные bindgen , такие как « my_bindgen [flags] wrapper_header.h -o [output\_path] -- [clang flags] ». Большая часть этого обрабатывается самой библиотекой bindgen . Чтобы увидеть пример такого использования, посетите external/rust/crates/libsqlite3-sys/android/build.rs .

Кроме того, для управления компиляцией библиотеки доступен полный набор свойств библиотеки, хотя их определение или изменение требуется редко.