Sistem build mendukung pembuatan binding bindgen melalui jenis modul rust_bindgen
. Bindgen menyediakan binding FFI Rust ke library C (dengan beberapa dukungan C++ terbatas, yang memerlukan setelan properti cppstd
).
Penggunaan rust_bindgen dasar
Berikut adalah contoh cara menentukan modul yang menggunakan bindgen, dan
cara menggunakan modul tersebut sebagai crate. Jika Anda perlu menggunakan binding bindgen melalui
makro include!()
, seperti untuk kode eksternal, lihat halaman
Generator Kode.
Contoh library C yang akan dipanggil dari Rust
Contoh library C yang menentukan 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);
}
Menentukan modul rust_bindgen
Tentukan header wrapper, 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"
Tentukan 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 cara menggunakan flag bindgen, lihat bagian manual bindgen tentang Menyesuaikan Binding yang Dihasilkan.
Jika Anda menggunakan bagian ini untuk menentukan modul rust_bindgen
sebagai prasyarat untuk
menggunakan makro include!()
, kembali ke Prasyarat
di halaman Pembuat Sumber. Jika tidak, lanjutkan ke bagian berikutnya.
Menggunakan pengikatan 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 membangun program biner.
Menguji binding Bindgen
Binding bindgen biasanya berisi sejumlah pengujian tata letak yang dihasilkan untuk mencegah ketidakcocokan tata letak memori. AOSP merekomendasikan agar Anda menentukan modul pengujian untuk pengujian ini, dan pengujian dijalankan sebagai bagian dari rangkaian pengujian normal project Anda.
Biner pengujian untuk ini dapat dengan mudah dibuat dengan menentukan 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 penautan
Binding yang dihasilkan biasanya sangat kecil, karena terdiri dari definisi jenis,
tanda tangan fungsi, dan konstanta terkait. Oleh karena itu, umumnya
sia-sia menautkan library ini secara dinamis. Kami telah menonaktifkan penautan dinamis
untuk modul ini sehingga penggunaannya melalui rustlibs
akan otomatis memilih varian
statis.
Secara default, modul rust_bindgen
memiliki properti visibility
[":__subpackages__"]
, yang hanya akan mengizinkan modul dalam file Android.bp
yang sama atau yang berada di bawahnya dalam hierarki direktori untuk melihatnya. Hal ini memiliki dua
tujuan:
- Hal ini mencegah penggunaan binding C mentah di tempat lain dalam hierarki.
- Tindakan ini menghindari masalah penautan berlian dengan campuran penautan statis dan dinamis.
Biasanya, Anda harus menyediakan library wrapper yang aman di sekitar modul yang dihasilkan yang telah Anda tambahkan di hierarki direktori yang sama dengan binding yang ditujukan untuk digunakan oleh developer lain. Jika cara ini tidak berhasil untuk kasus penggunaan Anda, Anda dapat menambahkan paket tambahan ke visibilitas. Saat menambahkan cakupan visibilitas tambahan, pastikan Anda tidak menambahkan dua cakupan yang dapat ditautkan ke proses yang sama pada masa mendatang, karena hal ini dapat menyebabkan kegagalan penautan.
Properti rust_bindgen penting
Properti yang ditentukan di bawah ini adalah 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
.
stem, name, crate_name
rust_bindgen
menghasilkan varian library, sehingga memiliki persyaratan yang sama dengan
modul rust_library
untuk properti stem
, name
, dan crate_name
. Lihat
Properti library Rust yang penting
untuk referensi.
wrapper_src
Ini adalah jalur relatif ke file header wrapper yang menyertakan header yang diperlukan
untuk binding ini. Ekstensi file menentukan cara menafsirkan header
dan menentukan flag -std
mana yang akan digunakan secara default. Ini dianggap sebagai header C
kecuali ekstensi adalah .hh
atau .hpp
. Jika header C++ Anda harus memiliki
ekstensi lain, tetapkan properti cpp_std
untuk mengganti perilaku default
yang mengasumsikan file adalah file C.
source_stem
Ini adalah nama file untuk file sumber yang dihasilkan. Kolom ini harus
ditentukan, meskipun Anda menggunakan binding sebagai crate, karena properti stem
hanya mengontrol nama file output untuk varian library yang dihasilkan.
Jika modul bergantung pada beberapa generator sumber (seperti bindgen
dan protobuf
)
sebagai sumber, bukan sebagai crate 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 ditentukan di
srcs
ke direktori OUT_DIR
umum, sehingga konflik di source_stem
akan
mengakibatkan file sumber yang dihasilkan ditimpa di direktori OUT_DIR
.
c_std
Ini adalah string yang merepresentasikan versi standar C yang akan digunakan. Nilai yang valid dicantumkan di bawah:
- 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. Hal ini tidak dapat disetel bersamaan dengan cpp_std
.
cpp_std
cpp_std
adalah string yang merepresentasikan versi standar C yang akan digunakan. Nilai 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 disetel, ekstensi file akan diabaikan dan header dianggap sebagai header C++. Hal ini tidak dapat disetel bersamaan dengan c_std
.
cflags
cflags
menyediakan daftar string flag Clang yang diperlukan untuk menafsirkan header dengan benar.
custom_bindgen
Untuk kasus penggunaan lanjutan, bindgen dapat digunakan sebagai library, yang menyediakan API yang dapat dimanipulasi sebagai bagian dari biner Rust kustom. Kolom custom_bindgen
mengambil nama
modul rust_binary_host
, yang menggunakan bindgen API, bukan
biner bindgen
normal.
Biner kustom ini harus menerima argumen dengan cara yang serupa dengan bindgen
, seperti
$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]
Sebagian besar hal ini ditangani oleh library bindgen
itu sendiri. Untuk melihat contoh penggunaan ini, buka external/rust/crates/libsqlite3-sys/android/build.rs.
Selain itu, kumpulan lengkap properti library tersedia untuk mengontrol kompilasi library, meskipun jarang perlu ditentukan atau diubah.
handle_static_inline dan static_inline_library
Kedua properti ini dimaksudkan untuk digunakan bersama dan memungkinkan produksi wrapper untuk fungsi inline statis yang dapat disertakan dalam binding bindgen yang diekspor.
Untuk menggunakannya, tetapkan handle_static_inline: true
dan tetapkan static_inline_library
ke
cc_library_static
yang sesuai yang menentukan modul rust_bindgen
sebagai
input sumber.
Contoh penggunaan:
rust_bindgen {
name: "libbindgen",
wrapper_src: "src/any.h",
crate_name: "bindgen",
stem: "libbindgen",
source_stem: "bindings",
// Produce bindings for static inline fucntions
handle_static_inline: true,
static_inline_library: "libbindgen_staticfns"
}
cc_library_static {
name: "libbindgen_staticfns",
// This is the rust_bindgen module defined above
srcs: [":libbindgen"],
// The include path to the header file in the generated c file is
// relative to build top.
include_dirs: ["."],
}