سیستم ساخت از تولید اتصالات bindgen از طریق نوع ماژول rust_bindgen
پشتیبانی می کند. Bindgen اتصالهای Rust FFI را به کتابخانههای C ارائه میکند (با پشتیبانی محدود C++، که نیاز به تنظیم ویژگی cppstd
دارد).
استفاده اولیه rust_bindgen
آنچه در زیر می آید مثالی از نحوه تعریف ماژولی است که از bindingen استفاده می کند و نحوه استفاده از آن ماژول به عنوان جعبه. اگر نیاز به استفاده از bindgen bindings از طریق یک ماکرو include!()
دارید، مانند کد خارجی، به صفحه Source Generators مراجعه کنید.
کتابخانه 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 را تعریف کنید
یک هدر wrapper، 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!()
استفاده کرده اید، در صفحه Source Generators به پیش نیاز بازگردید. اگر نه، به بخش های بعدی ادامه دهید.
از اتصالات به عنوان جعبه استفاده کنید
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
برای ساخت باینری صدا کنید.
اتصالات Bindingen را تست کنید
اتصالات 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",
}
دید و پیوند
اتصالات تولید شده معمولاً بسیار کوچک هستند، زیرا از تعاریف نوع، امضاهای تابع و ثابت های مرتبط تشکیل شده اند. در نتیجه، به طور کلی پیوند دادن این کتابخانه ها به صورت پویا بیهوده است. ما پیوند پویا را برای این ماژول ها غیرفعال کرده ایم تا استفاده از آنها از طریق rustlibs
به طور خودکار یک نوع ثابت را انتخاب کند.
بهطور پیشفرض، ماژولهای rust_bindgen
دارای ویژگی visibility
[":__subpackages__"]
هستند، که فقط به ماژولهای موجود در همان فایل Android.bp
یا زیر آن در سلسله مراتب دایرکتوری اجازه دیدن آن را میدهد. این دو هدف را دنبال می کند:
- استفاده از اتصالات C خام در جای دیگر درخت را منع می کند.
- از مسائل مرتبط با الماس با ترکیبی از پیوند استاتیک و پویا جلوگیری می کند.
معمولاً، شما باید یک کتابخانه پوشش ایمن در اطراف ماژول تولید شده که در همان درخت دایرکتوری اضافه کرده اید، فراهم کنید که برای توسعه دهندگان دیگر برای استفاده در نظر گرفته شده است. اگر این برای مورد استفاده شما کار نمی کند، می توانید بسته های اضافی را به قابلیت مشاهده اضافه کنید. هنگام افزودن دامنه های دید اضافی، لطفاً مراقب باشید که دو محدوده را که ممکن است در آینده به یک فرآیند مرتبط شوند اضافه نکنید، زیرا ممکن است پیوند داده نشود.
خواص rust_bindgen قابل توجه
ویژگی های تعریف شده در زیر علاوه بر ویژگی های مشترک مهم مهم است که برای همه ماژول ها اعمال می شود. اینها یا به ویژه برای ماژول های Rust bindgen مهم هستند، یا رفتار منحصر به فرد مخصوص نوع ماژول rust_bindgen
را نشان می دهند.
ساقه، نام، crate_name
rust_bindgen
انواع کتابخانه را تولید می کند، بنابراین آنها نیازمندی های مشابهی با ماژول های rust_library
برای ویژگی های stem
، name
و crate_name
دارند. برای مرجع به ویژگی های کتابخانه Notable Rust مراجعه کنید.
wrapper_src
این مسیر نسبی به یک فایل هدر wrapper است که شامل سرصفحه های مورد نیاز برای این اتصالات است. پسوند فایل نحوه تفسیر هدر را تعیین می کند و تعیین می کند که کدام پرچم -std
به طور پیش فرض استفاده شود. فرض میشود که این یک هدر C باشد، مگر اینکه پسوند .hh
یا .hpp
باشد. اگر هدر ++C شما باید پسوند دیگری داشته باشد، ویژگی cpp_std
را طوری تنظیم کنید که رفتار پیشفرض را که فرض میکند فایل یک فایل C است، لغو کند.
منبع_ساقه
این نام فایل برای فایل منبع تولید شده است. این فیلد باید تعریف شود، حتی اگر از اتصالات به عنوان جعبه استفاده می کنید، زیرا ویژگی stem
فقط نام فایل خروجی را برای انواع کتابخانه تولید شده کنترل می کند. اگر یک ماژول به مولدهای منبع متعدد (مانند bindgen
و protobuf
) به عنوان منبع به جای جعبه های rustlibs
وابسته است، باید اطمینان حاصل کنید که همه مولدهای منبع که وابسته به آن ماژول هستند دارای مقادیر source_stem
منحصر به فرد هستند. ماژولهای وابسته منابع را از تمام وابستگیهای SourceProvider
که در srcs
تعریف شدهاند در یک فهرست مشترک OUT_DIR
کپی میکنند، بنابراین برخورد در source_stem
منجر به بازنویسی فایلهای منبع تولید شده در فهرست OUT_DIR
میشود.
c_std
این رشته ای است که نشان می دهد کدام نسخه استاندارد C باید استفاده شود. مقادیر معتبر در زیر لیست شده است:
- یک نسخه خاص، مانند
"gnu11"
. -
"experimental"
که مقداری است که توسط سیستم ساخت درbuild/soong/cc/config/global.go
تعریف شده است، ممکن است از نسخههای پیشنویس مانند C++1z در صورت موجود بودن استفاده کند. - Unset یا
""
, که نشان می دهد باید از پیش فرض سیستم ساخت استفاده شود.
اگر این تنظیم شود، پسوند فایل نادیده گرفته می شود و هدر یک هدر C فرض می شود. این را نمی توان همزمان با cpp_std
تنظیم کرد.
cpp_std
cpp_std
رشته ای است که نشان می دهد کدام نسخه استاندارد C باید استفاده شود. مقادیر معتبر:
- یک نسخه خاص، مانند
"gnu++11"
-
"experimental"
که مقداری است که توسط سیستم ساخت درbuild/soong/cc/config/global.go
تعریف شده است، ممکن است از نسخههای پیشنویس مانند C++1z در صورت موجود بودن استفاده کند. - Unset یا
""
, که نشان می دهد باید از پیش فرض سیستم ساخت استفاده شود.
اگر این تنظیم شود، پسوند فایل نادیده گرفته می شود و هدر یک هدر 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 مراجعه کنید.
علاوه بر این، مجموعه کاملی از ویژگی های کتابخانه برای کنترل کامپایل کتابخانه در دسترس است، اگرچه این ویژگی ها به ندرت نیاز به تعریف یا تغییر دارند.
handle_static_inline و static_inline_library
این دو ویژگی قرار است با هم استفاده شوند و امکان تولید لفافها را برای توابع درون خطی استاتیکی فراهم کنند که میتوانند در اتصالات bindgen صادراتی گنجانده شوند.
برای استفاده از آنها، handle_static_inline: true
تنظیم کنید و static_inline_library
روی یک cc_library_static
مربوطه تنظیم کنید که ماژول rust_bindgen
را به عنوان ورودی منبع تعریف می کند.
مثال استفاده:
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: ["."],
}