Hệ thống xây dựng hỗ trợ tạo liên kết bindgen thông qua loại mô-đun rust_bindgen . Bindgen cung cấp các liên kết Rust FFI cho các thư viện C (với một số hỗ trợ C++ hạn chế, yêu cầu đặt thuộc tính cppstd ).

Cách sử dụng Rust_bindgen cơ bản

Sau đây là ví dụ về cách xác định mô-đun sử dụng bindgen và cách sử dụng mô-đun đó làm thùng. Nếu bạn cần sử dụng liên kết bindgen thông qua macro include!() , chẳng hạn như đối với mã bên ngoài, hãy xem trang Trình tạo nguồn .

Thư viện C mẫu để gọi từ Rust

Sau đây là một thư viện C mẫu xác định cấu trúc và hàm để sử dụng trong 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);
}

Xác định mô-đun Rust_bindgen

Xác định tiêu đề trình bao bọc, external/rust/libbuzz/libbuzz_wrapper.h , bao gồm tất cả các tiêu đề có liên quan:

// Include headers that are required for generating bindings in a wrapper header.
#include "libbuzz.h"

Xác định tệp Android.bpexternal/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"],
}

Để tìm hiểu thêm về cách sử dụng cờ bindgen, hãy xem phần hướng dẫn sử dụng bindgen trên Tùy chỉnh các ràng buộc được tạo .

Nếu bạn đã sử dụng phần này để xác định mô-đun rust_bindgen làm điều kiện tiên quyết để sử dụng macro include!() , hãy quay lại Điều kiện tiên quyết trên trang Trình tạo nguồn. Nếu không, hãy tiếp tục với các phần tiếp theo.

Sử dụng các ràng buộc như một cái thùng

Tạo external/rust/hello_bindgen/Android.bp với nội dung sau:

rust_binary {
   name: "hello_bindgen",
   srcs: ["main.rs"],

   // Add the rust_bindgen module as if it were a rust_library dependency.
   rustlibs: ["libbuzz_bindgen"],
}

Tạo external/rust/hello_bindgen/src/main.rs với nội dung sau:

//! 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) }
}

Cuối cùng, gọi m hello_bindgen để xây dựng hệ nhị phân.

Kiểm tra các ràng buộc Bindgen

Các liên kết Bindgen thường chứa một số thử nghiệm bố cục được tạo để ngăn chặn bố cục bộ nhớ không khớp. AOSP khuyên bạn nên xác định một mô-đun thử nghiệm cho các thử nghiệm này và các thử nghiệm đó chạy như một phần của bộ thử nghiệm thông thường trong dự án của bạn.

Có thể dễ dàng tạo một tệp nhị phân thử nghiệm cho những thứ này bằng cách xác định mô-đun rust_test trong 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",
}

Khả năng hiển thị và liên kết

Các liên kết được tạo thường rất nhỏ vì chúng bao gồm các định nghĩa kiểu, chữ ký hàm và các hằng số liên quan. Kết quả là, việc liên kết động các thư viện này thường là lãng phí. Chúng tôi đã vô hiệu hóa liên kết động cho các mô-đun này để việc sử dụng chúng thông qua rustlibs sẽ tự động chọn một biến thể tĩnh.

Theo mặc định, các mô-đun rust_bindgen có thuộc tính visibility[":__subpackages__"] , thuộc tính này sẽ chỉ cho phép các mô-đun trong cùng một tệp Android.bp hoặc các mô-đun bên dưới nó trong hệ thống phân cấp thư mục có thể nhìn thấy nó. Điều này phục vụ hai mục đích:

  • Nó không khuyến khích việc sử dụng các liên kết C thô ở nơi khác trong cây.
  • Nó tránh được các vấn đề liên kết kim cương bằng cách kết hợp liên kết tĩnh và liên kết động.

Thông thường, bạn nên cung cấp một thư viện trình bao bọc an toàn xung quanh mô-đun được tạo mà bạn đã thêm vào trong cùng cây thư mục với các liên kết dành cho các nhà phát triển khác sử dụng. Nếu điều này không hiệu quả với trường hợp sử dụng của bạn, bạn có thể thêm các gói bổ sung vào khả năng hiển thị . Khi thêm phạm vi hiển thị bổ sung, vui lòng lưu ý rằng bạn không thêm hai phạm vi có thể được liên kết vào cùng một quy trình trong tương lai vì điều này có thể không liên kết được.

Thuộc tính Rust_bindgen đáng chú ý

Các thuộc tính được xác định bên dưới là phần bổ sung cho các thuộc tính chung quan trọng áp dụng cho tất cả các mô-đun. Đây là những điều đặc biệt quan trọng đối với các mô-đun Rust bindgen hoặc thể hiện hành vi độc đáo dành riêng cho loại mô-đun rust_bindgen .

thân, tên, thùng_name

rust_bindgen tạo ra các biến thể thư viện, vì vậy chúng có chung yêu cầu với các mô-đun rust_library cho các thuộc tính stem , namecrate_name . Xem Thuộc tính thư viện Rust đáng chú ý để tham khảo.

bao bọc_src

Đây là đường dẫn tương đối đến tệp tiêu đề trình bao bọc bao gồm các tiêu đề cần thiết cho các liên kết này. Phần mở rộng tệp xác định cách diễn giải tiêu đề và xác định cờ -std nào sẽ được sử dụng theo mặc định. Đây được coi là tiêu đề C trừ khi phần mở rộng là .hh hoặc .hpp . Nếu tiêu đề C++ của bạn phải có một số tiện ích mở rộng khác, hãy đặt thuộc tính cpp_std để ghi đè hành vi mặc định giả sử tệp là tệp C.

nguồn_stem

Đây là tên tệp cho tệp nguồn được tạo . Trường này phải được xác định, ngay cả khi bạn đang sử dụng các liên kết làm thùng, vì thuộc tính stem chỉ kiểm soát tên tệp đầu ra cho các biến thể thư viện được tạo. Nếu một mô-đun phụ thuộc vào nhiều trình tạo nguồn (chẳng hạn như bindgenprotobuf ) dưới dạng nguồn thay vì các thùng thông qua rustlibs , thì bạn phải đảm bảo rằng tất cả các trình tạo nguồn phụ thuộc vào mô-đun đó đều có các giá trị source_stem duy nhất. Các mô-đun phụ thuộc sao chép nguồn từ tất cả các phần phụ thuộc SourceProvider được xác định trong srcs vào thư mục OUT_DIR chung, do đó xung đột trong source_stem sẽ dẫn đến các tệp nguồn được tạo bị ghi đè trong thư mục OUT_DIR .

c_std

Đây là một chuỗi biểu thị phiên bản chuẩn C nào sẽ được sử dụng. Các giá trị hợp lệ được liệt kê dưới đây:

  • Một phiên bản cụ thể, chẳng hạn như "gnu11" .
  • "experimental" , là giá trị được xác định bởi hệ thống xây dựng trong build/soong/cc/config/global.go , có thể sử dụng các phiên bản nháp như C++1z khi chúng có sẵn.
  • Bỏ đặt hoặc "" , cho biết nên sử dụng mặc định của hệ thống xây dựng.

Nếu điều này được đặt, phần mở rộng tệp sẽ bị bỏ qua và tiêu đề được coi là tiêu đề C. Điều này không thể được đặt cùng lúc với cpp_std .

cpp_std

cpp_std là một chuỗi biểu thị phiên bản chuẩn C nào sẽ được sử dụng. Giá trị hợp lệ:

  • Một phiên bản cụ thể, chẳng hạn như "gnu++11"
  • "experimental" , là giá trị được xác định bởi hệ thống xây dựng trong build/soong/cc/config/global.go , có thể sử dụng các phiên bản nháp như C++1z khi chúng có sẵn.
  • Bỏ đặt hoặc "" , cho biết nên sử dụng mặc định của hệ thống xây dựng.

Nếu điều này được đặt, phần mở rộng tệp sẽ bị bỏ qua và tiêu đề được coi là tiêu đề C++. Điều này không thể được đặt cùng lúc với c_std .

cflag

cflags cung cấp danh sách chuỗi các cờ Clang cần thiết để diễn giải chính xác các tiêu đề.

custom_bindgen

Đối với các trường hợp sử dụng nâng cao, bindgen có thể được sử dụng làm thư viện, cung cấp API có thể được thao tác như một phần của tệp nhị phân Rust tùy chỉnh. Trường custom_bindgen lấy tên mô-đun của mô-đun rust_binary_host , sử dụng API bindgen thay vì nhị phân bindgen thông thường.

Nhị phân tùy chỉnh này phải mong đợi các đối số theo kiểu tương tự như bindgen , chẳng hạn như

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

Hầu hết việc này được xử lý bởi chính thư viện bindgen . Để xem ví dụ về cách sử dụng này, hãy truy cập external/rust/crates/libsqlite3-sys/android/build.rs .

Ngoài ra, tập hợp đầy đủ các thuộc tính thư viện có sẵn để kiểm soát việc biên dịch thư viện, mặc dù những thuộc tính này hiếm khi cần xác định hoặc thay đổi.