Sistem build mendukung pembuatan pengikatan bindgen melalui jenis modul rust_bindgen
. Bindgen menyediakan pengikatan Rust FFI ke perpustakaan C (dengan beberapa dukungan C++ terbatas, yang memerlukan pengaturan properti cppstd
).
Penggunaan dasar Rust_bindgen
Berikut ini adalah contoh cara mendefinisikan modul yang menggunakan bindgen, dan cara menggunakan modul tersebut sebagai peti. Jika Anda perlu menggunakan pengikatan bindgen melalui makro include!()
, misalnya untuk kode eksternal, lihat halaman Generator Sumber .
Contoh perpustakaan C untuk dipanggil dari Rust
Contoh pustaka C yang mendefinisikan struct dan fungsi untuk digunakan di Rust adalah sebagai berikut.
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);
}
Tentukan modul Rust_bindgen
Tentukan header pembungkus, external/rust/libbuzz/libbuzz_wrapper.h
, yang mencakup semua header yang relevan:
// Include headers that are required for generating bindings in a wrapper header.
#include "libbuzz.h"
Definisikan file Android.bp
sebagai 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"],
}
Untuk mempelajari lebih lanjut tentang penggunaan tanda bindgen, lihat bagian manual bindgen tentang Menyesuaikan Binding yang Dihasilkan .
Jika Anda menggunakan bagian ini untuk mendefinisikan modul rust_bindgen
sebagai prasyarat untuk menggunakan include!()
, kembali ke Prasyarat di halaman Generator Sumber. Jika tidak, lanjutkan ke bagian berikutnya.
Gunakan binding sebagai peti
Buat external/rust/hello_bindgen/Android.bp
dengan konten berikut:
rust_binary {
name: "hello_bindgen",
srcs: ["main.rs"],
// Add the rust_bindgen module as if it were a rust_library dependency.
rustlibs: ["libbuzz_bindgen"],
}
Buat external/rust/hello_bindgen/src/main.rs
dengan konten berikut:
//! 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) }
}
Terakhir, panggil m hello_bindgen
untuk membuat biner.
Uji ikatan Bindgen
Binding Bindgen biasanya berisi sejumlah tes tata letak yang dihasilkan untuk mencegah ketidakcocokan tata letak memori. AOSP merekomendasikan agar Anda memiliki modul pengujian yang ditentukan untuk pengujian ini, dan pengujian tersebut dijalankan sebagai bagian dari rangkaian pengujian normal proyek Anda.
Biner pengujian untuk ini dapat dengan mudah dibuat dengan mendefinisikan modul rust_test
di 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",
}
Visibilitas dan keterkaitan
Binding yang dihasilkan biasanya berukuran sangat kecil, karena terdiri dari definisi tipe, tanda tangan fungsi, dan konstanta terkait. Akibatnya, menghubungkan perpustakaan-perpustakaan ini secara dinamis biasanya sia-sia. Kami telah menonaktifkan tautan dinamis untuk modul-modul ini sehingga menggunakannya melalui rustlibs
akan secara otomatis memilih varian statis.
Secara default, modul rust_bindgen
memiliki properti visibility
[":__subpackages__"]
, yang hanya mengizinkan modul dalam file Android.bp
yang sama atau modul di bawahnya dalam hierarki direktori untuk melihatnya. Ini memiliki dua tujuan:
- Ini mencegah penggunaan pengikatan C mentah di tempat lain di pohon.
- Ini menghindari masalah tautan berlian dengan campuran tautan statis dan dinamis.
Biasanya, Anda harus menyediakan pustaka pembungkus yang aman di sekitar modul yang dihasilkan yang telah Anda tambahkan di pohon direktori yang sama dengan pengikatan yang dimaksudkan untuk digunakan oleh pengembang lain. Jika ini tidak berhasil untuk kasus penggunaan Anda, Anda dapat menambahkan paket tambahan ke visibilitas . Saat menambahkan cakupan visibilitas tambahan, harap berhati-hati agar Anda tidak menambahkan dua cakupan yang mungkin ditautkan ke proses yang sama di masa mendatang, karena hal ini mungkin gagal untuk ditautkan.
Properti karat_bindgen yang terkenal
Properti yang didefinisikan di bawah ini merupakan tambahan dari properti umum Penting yang berlaku untuk semua modul. Ini sangat penting untuk modul Rust bindgen, atau menunjukkan perilaku unik khusus untuk jenis modul rust_bindgen
.
batang, nama, nama_ peti
rust_bindgen
menghasilkan varian perpustakaan, sehingga mereka berbagi persyaratan yang sama dengan modul rust_library
untuk properti stem
, name
, dan crate_name
. Lihat Properti perpustakaan Rust yang terkenal untuk referensi.
wrapper_src
Ini adalah jalur relatif ke file header wrapper yang menyertakan header yang diperlukan untuk pengikatan ini. Ekstensi file menentukan cara menafsirkan header dan menentukan -std
flag mana yang akan digunakan secara default. Ini diasumsikan sebagai header C kecuali ekstensinya adalah .hh
atau .hpp
. Jika header C++ Anda harus memiliki ekstensi lain, setel properti cpp_std
untuk mengganti perilaku default yang mengasumsikan file tersebut adalah file C.
sumber_batang
Ini adalah nama file untuk file sumber yang dihasilkan . Bidang ini harus ditentukan, meskipun Anda menggunakan pengikatan sebagai peti, karena properti stem
hanya mengontrol nama file keluaran untuk varian pustaka yang dihasilkan. Jika sebuah modul bergantung pada beberapa generator sumber (seperti bindgen
dan protobuf
) sebagai sumber, bukan sebagai peti melalui rustlibs
, Anda harus memastikan bahwa semua generator sumber yang merupakan dependensi modul tersebut memiliki nilai source_stem
yang unik. Modul dependen menyalin sumber dari semua dependensi SourceProvider
yang didefinisikan dalam srcs
ke direktori OUT_DIR
umum, sehingga tabrakan di source_stem
akan mengakibatkan file sumber yang dihasilkan ditimpa di direktori OUT_DIR
.
c_std
Ini adalah string yang mewakili versi standar C mana yang akan digunakan. Nilai yang valid tercantum di bawah ini:
- Versi tertentu, seperti
"gnu11"
. -
"experimental"
, yang merupakan nilai yang ditentukan oleh sistem build dibuild/soong/cc/config/global.go
, dapat menggunakan versi draf seperti C++1z jika tersedia. - Tidak disetel atau
""
, yang menunjukkan bahwa default sistem build harus digunakan.
Jika ini disetel, ekstensi file akan diabaikan dan header dianggap sebagai header C. Ini tidak dapat disetel bersamaan dengan cpp_std
.
cpp_std
cpp_std
adalah string yang mewakili versi standar C mana yang akan digunakan. Nilai yang valid:
- Versi tertentu, seperti
"gnu++11"
-
"experimental"
, yang merupakan nilai yang ditentukan oleh sistem build dibuild/soong/cc/config/global.go
, dapat menggunakan versi draf seperti C++1z jika tersedia. - Tidak disetel atau
""
, yang menunjukkan bahwa default sistem build harus digunakan.
Jika ini disetel, ekstensi file akan diabaikan dan header diasumsikan sebagai header C++. Ini tidak dapat disetel bersamaan dengan c_std
.
cflag
cflags
menyediakan daftar string flag Clang yang diperlukan untuk menafsirkan header dengan benar.
custom_bindgen
Untuk kasus penggunaan tingkat lanjut, bindgen dapat digunakan sebagai perpustakaan, menyediakan API yang dapat dimanipulasi sebagai bagian dari biner Rust khusus. Bidang custom_bindgen
mengambil nama modul dari modul rust_binary_host
, yang menggunakan API bindgen, bukan biner bindgen
normal.
Biner khusus ini harus mengharapkan argumen dengan cara yang mirip dengan bindgen
, seperti
$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]
Sebagian besar ditangani oleh perpustakaan bindgen
itu sendiri. Untuk melihat contoh penggunaan ini, kunjungi external/rust/crates/libsqlite3-sys/android/build.rs .
Selain itu, set lengkap properti perpustakaan tersedia untuk mengontrol kompilasi perpustakaan, meskipun ini jarang perlu didefinisikan atau diubah.