Yapı sistemi, rust_bindgen modül türü aracılığıyla bağlama bağlamaları oluşturmayı destekler. Bindgen, C kitaplıklarına Rust FFI bağlamaları sağlar ( cppstd özelliğinin ayarlanmasını gerektiren bazı sınırlı C++ desteğiyle).

Temel Rust_bindgen kullanımı

Aşağıda, bağlayıcı kullanan bir modülün nasıl tanımlanacağına ve bu modülün kasa olarak nasıl kullanılacağına dair bir örnek yer almaktadır. Harici kod gibi bir include!() makrosu aracılığıyla bağlama bağlamaları kullanmanız gerekiyorsa, Kaynak Oluşturucular sayfasına bakın.

Rust'tan çağrılacak örnek C kütüphanesi

Rust'ta kullanılacak bir yapı ve işlevi tanımlayan örnek bir C kütüphanesi aşağıdadır.

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);
}

Bir Rust_bindgen modülü tanımlayın

İlgili tüm başlıkları içeren external/rust/libbuzz/libbuzz_wrapper.h bir sarmalayıcı başlığı tanımlayın:

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

Android.bp dosyasını external/rust/libbuzz/Android.bp olarak tanımlayın:

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"],
}

Bağlama bayraklarını kullanma hakkında daha fazla bilgi edinmek için Oluşturulan Bağlamaları Özelleştirme konusundaki bağlama kılavuzu bölümüne bakın.

Bu bölümü include!() makrosunu kullanmanın ön koşulu olarak bir rust_bindgen modülünü tanımlamak için kullandıysanız, Kaynak Oluşturucular sayfasında Önkoşul'a dönün. Değilse sonraki bölümlere geçin.

Bağlamaları sandık olarak kullanın

Aşağıdaki içerikle external/rust/hello_bindgen/Android.bp oluşturun:

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

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

Aşağıdaki içerikle external/rust/hello_bindgen/src/main.rs oluşturun:

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

Son olarak ikili dosyayı oluşturmak için m hello_bindgen çağırın.

Bindgen bağlamalarını test edin

Bindgen bağlamaları genellikle bellek düzeni uyumsuzluklarını önlemek için bir dizi oluşturulmuş düzen testi içerir. AOSP, bu testler için tanımlanmış bir test modülüne sahip olmanızı ve testlerin projenizin normal test paketinin bir parçası olarak çalıştırılmasını önerir.

Bunlar için bir test ikili dosyası external/rust/hello_bindgen/Android.bp dosyasında bir rust_test modülü tanımlanarak kolayca üretilebilir:

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",
}

Görünürlük ve bağlantı

Tür tanımları, işlev imzaları ve ilgili sabitlerden oluştuğu için oluşturulan bağlamalar genellikle çok küçüktür. Sonuç olarak, bu kütüphaneleri dinamik olarak birbirine bağlamak genellikle israftır. Bu modüller için dinamik bağlantıyı devre dışı bıraktık, böylece bunları rustlibs aracılığıyla kullanmak otomatik olarak statik bir değişken seçecektir.

Varsayılan olarak, rust_bindgen modülleri [":__subpackages__"] visibility özelliğine sahiptir; bu, yalnızca aynı Android.bp dosyasındaki veya dizin hiyerarşisinde onun altındaki modüllerin onu görmesine izin verir. Bu iki amaca hizmet eder:

  • Ağacın başka yerlerinde ham C bağlamalarının kullanılmasını engeller.
  • Statik ve dinamik bağlantının bir karışımıyla elmas bağlantı sorunlarını önler.

Genellikle, diğer geliştiricilerin kullanması amaçlanan bağlamalarla aynı dizin ağacına eklediğiniz oluşturulan modülün etrafına güvenli bir sarmalayıcı kitaplığı sağlamanız gerekir. Bu, kullanım durumunuz için işe yaramazsa görünürlüğe ek paketler ekleyebilirsiniz. Ek görünürlük kapsamları eklerken lütfen gelecekte aynı sürece bağlanabilecek iki kapsamı eklememeye dikkat edin; aksi takdirde bağlantı kurulamaz.

Dikkate değer Rust_bindgen özellikleri

Aşağıda tanımlanan özellikler, tüm modüller için geçerli olan Önemli ortak özelliklere ek olarak verilmiştir. Bunlar ya Rust bağlama modülleri için özellikle önemlidir ya da rust_bindgen modül tipine özgü benzersiz davranışlar sergiler.

kök, ad, sandık_adı

rust_bindgen kitaplık değişkenleri ürettiğinden, stem , name ve crate_name özellikleri için rust_library modülleriyle aynı gereksinimleri paylaşırlar. Referans için Önemli Rust kitaplığı özelliklerine bakın.

sarmalayıcı_src

Bu, bu bağlamalar için gereken başlıkları içeren sarmalayıcı başlık dosyasının göreceli yoludur. Dosya uzantısı, başlığın nasıl yorumlanacağını ve varsayılan olarak hangi -std bayrağının kullanılacağını belirler. Uzantı .hh veya .hpp olmadığı sürece bunun bir C başlığı olduğu varsayılır. C++ başlığınızın başka bir uzantıya sahip olması gerekiyorsa cpp_std özelliğini, dosyanın bir C dosyası olduğunu varsayan varsayılan davranışı geçersiz kılacak şekilde ayarlayın.

kaynak_stem

Bu , oluşturulan kaynak dosyanın dosya adıdır. Bağlamaları bir kasa olarak kullanıyor olsanız bile bu alanın tanımlanması gerekir , çünkü stem özelliği yalnızca oluşturulan kitaplık varyantları için çıktı dosya adını kontrol eder. Bir modül, rustlibs aracılığıyla kasalar yerine kaynak olarak birden fazla kaynak oluşturucuya ( bindgen ve protobuf gibi) bağlıysa, o modülün bağımlılığı olan tüm kaynak oluşturucuların benzersiz source_stem değerlerine sahip olduğundan emin olmalısınız. Bağımlı modüller, srcs tanımlanan tüm SourceProvider bağımlılıklarından kaynakları ortak bir OUT_DIR dizinine kopyalar; böylece source_stem çarpışmalar, OUT_DIR dizininde oluşturulan kaynak dosyalarının üzerine yazılmasına neden olur.

c_std

Bu, hangi C standardı sürümünün kullanılacağını temsil eden bir dizedir. Geçerli değerler aşağıda listelenmiştir:

  • "gnu11" gibi belirli bir sürüm.
  • build/soong/cc/config/global.go dosyasında derleme sistemi tarafından tanımlanan bir değer olan "experimental" , kullanılabilir olduklarında C++1z gibi taslak sürümleri kullanabilir.
  • Unset veya "" , derleme sistemi varsayılanının kullanılması gerektiğini belirtir.

Bu ayarlanırsa dosya uzantısı göz ardı edilir ve başlığın bir C başlığı olduğu varsayılır. Bu cpp_std ile aynı anda ayarlanamaz.

cpp_std

cpp_std hangi C standart sürümünün kullanılacağını temsil eden bir dizedir. Geçerli değerler:

  • "gnu++11" gibi belirli bir sürüm
  • build/soong/cc/config/global.go dosyasında derleme sistemi tarafından tanımlanan bir değer olan "experimental" , kullanılabilir olduklarında C++1z gibi taslak sürümleri kullanabilir.
  • Unset veya "" , derleme sistemi varsayılanının kullanılması gerektiğini belirtir.

Bu ayarlanırsa dosya uzantısı göz ardı edilir ve başlığın bir C++ başlığı olduğu varsayılır. Bu c_std ile aynı anda ayarlanamaz.

bayraklar

cflags başlıkları doğru şekilde yorumlamak için gereken Clang bayraklarının bir dize listesini sağlar.

özel_bindgen

Gelişmiş kullanım örnekleri için, Bingen, özel bir Rust ikili dosyasının parçası olarak işlenebilen bir API sağlayarak bir kitaplık olarak kullanılabilir. custom_bindgen alanı, normal bindgen ikili dosyası yerine bingen API'sini kullanan bir rust_binary_host modülünün modül adını alır.

Bu özel ikili dosyanın, bindgen benzer şekilde bağımsız değişkenler beklemesi gerekir; örneğin

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

Bunların çoğu, bindgen kütüphanesinin kendisi tarafından işlenir. Bu kullanımın bir örneğini görmek için external/rust/crates/libsqlite3-sys/android/build.rs adresini ziyaret edin.

Ek olarak, kütüphanenin derlenmesini kontrol etmek için kütüphane özelliklerinin tam seti mevcuttur, ancak bunların nadiren tanımlanmasına veya değiştirilmesine ihtiyaç vardır.