سیستم ساخت از تولید اتصالات 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: ["."],
    }