يتيح نظام الإنشاء إنشاء عمليات ربط bindgen من خلال نوع rust_bindgen
الوحدة. توفّر أداة Bindgen عمليات ربط Rust FFI بمكتبات C (مع بعض
الدعم المحدود لـ C++، والذي يتطلّب ضبط السمة cppstd
).
الاستخدام الأساسي لـ rust_bindgen
في ما يلي مثال على كيفية تحديد وحدة تستخدِم bindgen، و
كيفية استخدام هذه الوحدة كحزمة. إذا كنت بحاجة إلى استخدام عمليات ربط bindgen من خلال
رمز برمجي include!()
، مثل الرمز البرمجي الخارجي، اطّلِع على صفحة
أدوات إنشاء المصادر.
مثال على مكتبة 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!()
، ارجع إلى الشرط الأساسي
في صفحة "مولدّات المصادر". إذا لم يكن الأمر كذلك، انتقِل إلى الأقسام التالية.
استخدام عمليات الربط كصندوق
أنشئ 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 الأوّلي في أي مكان آخر في الشجرة.
- ويتجنّب هذا الأسلوب مشاكل الربط على شكل ماسة من خلال مزيج من الربط الثابت والديناميكي.
وعادةً ما يكون عليك توفير مكتبة ملفّ لفّ آمن حول الوحدة التي تم إنشاؤها والذي أضفته إلى شجرة الدليل نفسها التي تتضمّن عمليات الربط المخصّصة لاستخدام المطوّرين الآخرين. إذا لم تنجح هذه الطريقة في حلّ مشكلة حالة الاستخدام، يمكنك إضافة حِزم إضافية إلى مستوى العرض. عند إضافة نطاقات رؤية إضافية، يُرجى الحرص على عدم إضافة نطاقَين قد يتم ربطهما في العملية نفسها في المستقبل، لأنّ ذلك قد يؤدي إلى عدم الربط.
سمات rust_bindgen البارزة
إنّ الخصائص المحدّدة أدناه هي بالإضافة إلى الخصائص الشائعة والمهمة
التي تنطبق على جميع الوحدات. هذه الوحدات إما مهمة بشكل خاص لوحدات Rust
bindgen، أو تُظهر سلوكًا فريدًا خاصًا بنوع وحدة rust_bindgen
.
stem، وname، وcrate_name
تُنشئ rust_bindgen
صِيغ مكتبة، لذا تتشارك المتطلبات نفسها مع
وحدات rust_library
للسمات stem
وname
وcrate_name
. اطّلِع على
خصائص مكتبة Rust البارزة
للرجوع إليها.
wrapper_src
هذا هو المسار النسبي لملف عنوان ملف لفّ يتضمن العناوين المطلوبة
لعمليات الربط هذه. يحدِّد امتداد الملف كيفية تفسير العنوان ويحدِّد علامة -std
التي سيتم استخدامها تلقائيًا. من المفترض أن يكون هذا العنوان هو C
ما لم تكون الإضافة .hh
أو .hpp
. إذا كان يجب أن يتضمّن عنوان C++
إضافة أخرى، اضبط السمة cpp_std
لإلغاء السلوك التلقائي
الذي يفترض أنّ الملف هو ملف C.
source_stem
هذا هو اسم ملف المصدر الذي تم إنشاؤه. يجب
تحديد هذا الحقل، حتى إذا كنت تستخدم عمليات الربط كمجموعة، لأنّ السمة stem
تتحكم فقط في اسم ملف الإخراج لخيارات المكتبة التي تم إنشاؤها.
إذا كانت إحدى الوحدات تعتمد على أدوات إنشاء مصادر متعددة (مثل bindgen
وprotobuf
)
كمصدر بدلاً من استخدامها كحِزم من خلال rustlibs
، يجب التأكّد من أنّ جميع أدوات إنشاء المصادر
التي تعتمد عليها هذه الوحدة تتضمّن قيم source_stem
فريدة. تنسخ الوحدات التابعة
المصادر من جميع تبعيات SourceProvider
التي تم تحديدها في
srcs
إلى دليل OUT_DIR
شائع، لذا فإنّ حدوث تعارضات في source_stem
يؤدي
إلى استبدال ملفات المصدر التي تم إنشاؤها في دليل OUT_DIR
.
c_std
هذه سلسلة تمثّل إصدار C-standard الذي يجب استخدامه. في ما يلي القيم الصالحة:
- إصدار معيّن، مثل
"gnu11"
"experimental"
هي قيمة يحدّدها نظام الإنشاء فيbuild/soong/cc/config/global.go
، وقد تستخدم نُسخًا مسودّة مثل C++1z عند توفّرها.- غير محدّد أو
""
، ما يشير إلى أنّه يجب استخدام الإعداد التلقائي لنظام الإنشاء.
في حال ضبط هذا الخيار، يتم تجاهل امتداد الملف ويُفترض أن يكون العنوان
عنوان C. لا يمكن ضبط هذا الخيار في الوقت نفسه الذي يتم فيه ضبط cpp_std
.
cpp_std
cpp_std
هي سلسلة تمثل إصدار C العادي المطلوب استخدامه. قيم صالحة:
- إصدار معيّن، مثل
"gnu++11"
"experimental"
هي قيمة يحدّدها نظام الإنشاء فيbuild/soong/cc/config/global.go
، وقد تستخدم نُسخًا مسودّة مثل C++1z عند توفّرها.- غير محدّد أو
""
، ما يشير إلى أنّه يجب استخدام الإعداد التلقائي لنظام الإنشاء.
في حال ضبط هذا الخيار، يتم تجاهل امتداد الملف ويُفترض أنّ العنوان هو عنوان C++. لا يمكن ضبط هذا الخيار في الوقت نفسه الذي يتم فيه ضبط c_std
.
cflags
يوفّر cflags
قائمة سلاسل بعلامات Clang المطلوبة لتفسير
العناوين بشكل صحيح.
custom_bindgen
بالنسبة إلى حالات الاستخدام المتقدّمة، يمكن استخدام bindgen كمكتبة، ما يوفر واجهة برمجة تطبيقات يمكن تعديلها كجزء من ملف ثنائي مخصّص لبرنامج Rust. يأخذ الحقل custom_bindgen
اسم ملف rust_binary_host
الذي يستخدم واجهة برمجة التطبيقات bindgen بدلاً
من ملف bindgen
الثنائي العادي.
يجب أن يتوقّع هذا الثنائي المخصّص وسيطات بطريقة مشابهة لـ bindgen
، مثل
$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]
وتتولى مكتبة bindgen
معظم هذه الإجراءات. للاطّلاع على مثال على استخدام
هذا الإجراء، يُرجى الانتقال إلى external/rust/crates/libsqlite3-sys/android/build.rs.
بالإضافة إلى ذلك، تتوفّر المجموعة الكاملة من سمات المكتبة للتحكّم في compiling المكتبة، على الرغم من أنّه نادرًا ما تحتاج هذه السمات إلى التحديد أو التغيير.
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: ["."],
}