Derleme sistemi, rust_bindgen modül türü aracılığıyla bindgen bağlamalarının oluşturulmasını destekler. Bindgen, C kitaplıkları için Rust FFI bağlamaları sağlar (bazı sınırlı C++ desteğiyle birlikte, bu da cppstd özelliğinin ayarlanmasını gerektirir).

Temel rust_bindgen kullanımı

Aşağıda, bindgen kullanan bir modülün nasıl tanımlanacağına ve bu modülün nasıl sandık olarak kullanılacağına dair bir örnek verilmiştir. Harici kod gibi durumlarda include!() makrosu aracılığıyla bindgen bağlamalarını kullanmanız gerekiyorsa Kaynak Oluşturucular sayfasına bakın.

Rust'tan çağrılacak örnek C kitaplığı

Rust'ta kullanılacak bir yapı ve işlev tanımlayan örnek bir C kitaplığı aşağıda verilmiştir.

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 modülü tanımlama

Tüm alakalı üstbilgileri içeren bir sarmalayıcı üstbilgisi (external/rust/libbuzz/libbuzz_wrapper.h) 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"],
}

Bindgen işaretlerini kullanma hakkında daha fazla bilgi edinmek için Özel Oluşturulan Bağlamalar bölümündeki bindgen kılavuzuna bakın.

rust_bindgen modülünü include!() makrosunu kullanmak için ön koşul olarak tanımlamak üzere bu bölümü kullandıysanız Kaynak Oluşturucular sayfasındaki Ön koşul'a dönün. Aksi takdirde, sonraki bölümlere geçin.

Bağlamaları sandık olarak kullanma

Aşağıdaki içeriklerle 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çeriklerle 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, ikiliyi oluşturmak için m hello_bindgen işlevini çağırın.

Test Bindgen bağlamaları

Bindgen bağlamaları, genellikle bellek düzeni uyuşmazlıklarını önlemek için bir dizi oluşturulmuş düzen testi içerir. AOSP, bu testler için tanımlanmış bir test modülünüz olmasını ve testlerin projenizin normal test paketi kapsamında çalıştırılmasını önerir.

Bunlar için bir test ikilisi, rust_test modülü external/rust/hello_bindgen/Android.bp içinde tanımlanarak kolayca oluşturulabilir:

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ı

Oluşturulan bağlamalar, tür tanımları, işlev imzaları ve ilgili sabitlerden oluştuğu için genellikle çok küçüktür. Bu nedenle, bu kitaplıkları dinamik olarak bağlamak genellikle gereksizdir. Bu modüller için dinamik bağlantıyı devre dışı bıraktık. Böylece, bu modüller rustlibs üzerinden kullanıldığında otomatik olarak statik bir varyant seçilecek.

Varsayılan olarak, rust_bindgen modüllerinin visibility özelliği [":__subpackages__"]'dir. Bu özellik, yalnızca aynı Android.bp dosyasındaki veya dizin hiyerarşisinde bu dosyanın altında yer alan modüllerin bu özelliği görmesine izin verir. Bu durum 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ı karışımıyla elmas bağlantı sorunlarını önler.

Genellikle, oluşturulan modülün etrafında güvenli bir sarmalayıcı kitaplık sağlamanız gerekir. Bu kitaplık, bağlamalarla aynı dizin ağacına eklenir ve diğer geliştiricilerin kullanması amaçlanır. Bu yöntem kullanım alanınız 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ı işleme bağlanabilecek iki kapsam eklememeye dikkat edin. Aksi takdirde bağlantı oluşturulamayabilir.

Önemli 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, Rust bindgen modülleri için özellikle önemlidir veya rust_bindgen modül türüne özgü benzersiz davranışlar sergiler.

stem, name, crate_name

rust_bindgen, kitaplık varyantları oluşturur. Bu nedenle, stem, name ve crate_name özellikleri için rust_library modülleriyle aynı koşulları paylaşır. Referans için Önemli Rust kitaplığı özellikleri bölümüne bakın.

wrapper_src

Bu, bu bağlamalar için gerekli başlıkları içeren bir sarmalayıcı başlık dosyasının göreli yoludur. Dosya uzantısı, üstbilginin nasıl yorumlanacağını ve varsayılan olarak hangi -std işaretinin 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ısı olması gerekiyorsa dosyanın C dosyası olduğunu varsayan varsayılan davranışı geçersiz kılmak için cpp_std özelliğini ayarlayın.

source_stem

Bu, oluşturulan kaynak dosyanın dosya adıdır. Bu alan, bağlamaları bir sandık olarak kullanıyor olsanız bile tanımlanmalıdır. Bunun nedeni, stem özelliğinin yalnızca oluşturulan kitaplık varyantlarının çıkış dosya adını kontrol etmesidir. Bir modül, rustlibs üzerinden paket olarak değil de kaynak olarak birden fazla kaynak oluşturucuya (ör. bindgen ve protobuf) bağlıysa bu modülün bağımlılıkları olan tüm kaynak oluşturucuların benzersiz source_stem değerlerine sahip olduğundan emin olmanız gerekir. Bağımlı modüller, SourceProvider içinde tanımlanan tüm srcs bağımlılıklarından kaynakları ortak bir OUT_DIR dizinine kopyalar. Bu nedenle, source_stem içindeki çakışmalar, oluşturulan kaynak dosyaların OUT_DIR dizininde üzerine yazılmasına neden olur.

c_std

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

  • "gnu11" gibi belirli bir sürüm.
  • "experimental", build/soong/cc/config/global.go içinde derleme sistemi tarafından tanımlanan bir değerdir. Bu değer, kullanıma sunulduğunda C++1z gibi taslak sürümleri kullanabilir.
  • Derleme sistemi varsayılanının kullanılması gerektiğini belirten ayarlanmamış veya "".

Bu ayar belirlenirse dosya uzantısı yoksayılır ve üstbilginin C üstbilgisi olduğu varsayılır. Bu ayar, cpp_std ile aynı anda yapılamaz.

cpp_std

cpp_std, hangi C standardı sürümünün kullanılacağını gösteren bir dizedir. Geçerli değerler:

  • Belirli bir sürüm (ör. "gnu++11")
  • "experimental", build/soong/cc/config/global.go içinde derleme sistemi tarafından tanımlanan bir değerdir. Bu değer, kullanıma sunulduğunda C++1z gibi taslak sürümleri kullanabilir.
  • Derleme sistemi varsayılanının kullanılması gerektiğini belirten ayarlanmamış veya "".

Bu ayar belirlenirse dosya uzantısı yoksayılır ve başlığın C++ başlığı olduğu varsayılır. Bu ayar, c_std ile aynı anda yapılamaz.

cflags

cflags, başlıkların doğru şekilde yorumlanması için gereken Clang işaretlerinin dize listesini sağlar.

custom_bindgen

İleri düzey kullanım alanları için bindgen, özel bir Rust ikilisinin parçası olarak değiştirilebilen bir API sağlayan bir kitaplık olarak kullanılabilir. custom_bindgen alanı, normal bindgen ikilisi yerine bindgen API'sini kullanan bir rust_binary_host modülünün modül adını alır.

Bu özel ikili, bindgen'ya benzer şekilde bağımsız değişkenler beklemelidir. Örneğin:

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

Bu işlemlerin çoğu bindgen kitaplığı tarafından gerçekleştirilir. Bu kullanımın bir örneğini görmek için external/rust/crates/libsqlite3-sys/android/build.rs adresini ziyaret edin.

Ayrıca, kitaplığın derlenmesini kontrol etmek için kitaplık özelliklerinin tamamı kullanılabilir. Ancak bu özelliklerin tanımlanması veya değiştirilmesi nadiren gerekir.

handle_static_inline ve static_inline_library

Bu iki özellik birlikte kullanılmak üzere tasarlanmıştır ve dışa aktarılan bindgen bağlamalarına dahil edilebilecek statik satır içi işlevler için sarmalayıcıların oluşturulmasına olanak tanır.

Bu işlevleri kullanmak için handle_static_inline: true ve static_inline_library değerini, rust_bindgen modülünü kaynak girişi olarak tanımlayan ilgili cc_library_static olarak ayarlayın.

Örnek kullanım:

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