מערכת הבנייה תומכת ביצירת כריכות bindgen דרך סוג המודול rust_bindgen . Bindgen מספק כריכות Rust FFI לספריות C (עם תמיכה מוגבלת ב-C++, הדורשת הגדרת המאפיין cppstd ).

שימוש בסיסי ב-rust_bindgen

להלן דוגמה כיצד להגדיר מודול המשתמש ב-bindgen, וכיצד להשתמש במודול זה בתור ארגז. אם אתה צריך להשתמש ב-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

הגדר כותרת עטיפה, 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!() , חזור אל Prerequisite בדף 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 כדי לבנות את הבינארי.

בדוק כריכות 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",
}

נראות והצמדה

כריכות שנוצרו הן בדרך כלל קטנות מאוד, מכיוון שהן מורכבות מהגדרות סוג, חתימות פונקציות וקבועים קשורים. כתוצאה מכך, זה בדרך כלל בזבזני לקשר ספריות אלה באופן דינמי. השבתנו קישור דינמי עבור מודולים אלה כך ששימוש בהם באמצעות rustlibs יבחר אוטומטית גרסה סטטית.

כברירת מחדל, למודול rust_bindgen יש מאפיין visibility של [":__subpackages__"] , אשר יאפשר רק למודולים באותו קובץ Android.bp או לאלה שמתחתיו בהיררכיית הספריות לראות אותו. זה משרת שתי מטרות:

  • זה מונע שימוש בקשרי C גולמיים במקומות אחרים בעץ.
  • זה מונע בעיות של קישור יהלומים עם שילוב של קישור סטטי ודינאמי.

בדרך כלל, עליך לספק ספריית מעטפת בטוחה מסביב למודול שנוצר שהוספת באותו עץ ספריות כמו ה-bindings שמיועד למפתחים אחרים להשתמש. אם זה לא עובד במקרה השימוש שלך, אתה יכול להוסיף חבילות נוספות לנראות . בעת הוספת היקפי נראות נוספים, אנא הקפד שלא תוסיף שני היקפים שעשויים להיות מקושרים לאותו תהליך בעתיד, מכיוון שזה עלול להיכשל בקישור.

מאפיינים בולטים של rust_bindgen

המאפיינים המוגדרים להלן מתווספים למאפיינים המשותפים החשובים החלים על כל המודולים. אלה חשובים במיוחד למודולי Rust bindgen, או שהם מציגים התנהגות ייחודית ספציפית לסוג המודול rust_bindgen .

stam, name, crate_name

rust_bindgen מייצר גרסאות של ספרייה, כך שהן חולקות את אותן דרישות עם המודולים rust_library עבור המאפיינים stem , name ו- crate_name . ראה מאפיינים בולטים של ספריית חלודה לעיון.

wrapper_src

זהו הנתיב היחסי לקובץ כותרות עטיפה הכולל את הכותרות הנדרשות עבור כריכות אלו. סיומת הקובץ קובעת כיצד לפרש את הכותרת וקובעת באיזה דגל -std להשתמש כברירת מחדל. ההנחה היא שזו כותרת C אלא אם כן הסיומת היא .hh או .hpp . אם לכותרת C++ שלך חייבת להיות סיומת אחרת, הגדר את המאפיין cpp_std כדי לעקוף את התנהגות ברירת המחדל שמניחה שהקובץ הוא קובץ C.

מקור_סטם

זהו שם הקובץ של קובץ המקור שנוצר . שדה זה חייב להיות מוגדר, גם אם אתה משתמש ב-bindings בתור ארגז, מכיוון שמאפיין stem שולט רק בשם קובץ הפלט עבור גרסאות הספרייה שנוצרו. אם מודול תלוי במחוללי מקור מרובים (כגון bindgen ו- protobuf ) כמקור ולא בתור ארגזים דרך rustlibs , עליך לוודא שלכל מחוללי המקור שהם תלות של אותו מודול יש ערכי source_stem ייחודיים. מודולים תלויים מעתיקים מקורות מכל התלות SourceProvider המוגדרות ב- srcs לספריית OUT_DIR משותפת, כך שהתנגשויות ב- source_stem יגרמו להחלפת קבצי המקור שנוצרו בספריית OUT_DIR .

c_std

זוהי מחרוזת המייצגת באיזו גרסה סטנדרטית C להשתמש. ערכים חוקיים מפורטים להלן:

  • גרסה ספציפית, כגון "gnu11" .
  • "experimental" , שהוא ערך שהוגדר על ידי מערכת ה-build ב- build/soong/cc/config/global.go , עשוי להשתמש בגרסאות טיוטה כמו C++1z כשהן זמינות.
  • בטל או "" , המציין שיש להשתמש בברירת המחדל של מערכת הבנייה.

אם זה מוגדר, מתעלמים מסיומת הקובץ ומניחים שהכותרת היא כותרת C. לא ניתן להגדיר זאת בו-זמנית עם cpp_std .

cpp_std

cpp_std היא מחרוזת המייצגת באיזו גרסה סטנדרטית C להשתמש. ערכים חוקיים:

  • גרסה ספציפית, כגון "gnu++11"
  • "experimental" , שהוא ערך שהוגדר על ידי מערכת ה-build ב- build/soong/cc/config/global.go , עשוי להשתמש בגרסאות טיוטה כמו C++1z כשהן זמינות.
  • בטל או "" , המציין שיש להשתמש בברירת המחדל של מערכת הבנייה.

אם זה מוגדר, מתעלמים מסיומת הקובץ ומניחים שהכותרת היא כותרת C++. לא ניתן להגדיר זאת בו-זמנית עם c_std .

cflags

cflags מספק רשימת מחרוזות של דגלי Clang הנדרשים כדי לפרש נכון את הכותרות.

custom_bindgen

עבור מקרי שימוש מתקדמים, ניתן להשתמש ב-bindgen כספרייה, המספקת API שניתן לתמרן כחלק מבינארי Rust מותאם אישית. השדה custom_bindgen לוקח את שם המודול של מודול rust_binary_host , המשתמש ב-bindgen API במקום הבינארי הרגיל bindgen .

בינארי מותאם אישית זה חייב לצפות לטיעונים בצורה דומה ל- bindgen , כגון

$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]

רוב זה מטופל על ידי ספריית bindgen עצמה. כדי לראות דוגמה לשימוש זה, בקר ב-extern/rust/crates/libsqlite3-sys/android/build.rs .

בנוסף, הסט המלא של מאפייני הספרייה זמין כדי לשלוט על הידור של הספרייה, אם כי לעתים נדירות יש צורך בהגדרה או שינוי של אלה.