Система сборки поддерживает создание привязок 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 .
Кроме того, для управления компиляцией библиотеки доступен полный набор свойств библиотеки, хотя их определение или изменение требуется редко.