Xarici funksiya interfeysləri (FFI)
İndiki iroha_ffi qutu C istehsalı üçün makro və xüsusiyyətlər təmin edir ABI bağlamalar Rust APIs. Burada istifadə olunur: Iroha növləri keçmək lazımdır FFI sərhədləri, məsələn SDK bağlamalar və ya ev sahibi inteqrasiyaları.
Niyə FFI
Bir funksiya olduqca abstrakt bir varlıqdır və əksər dillər bir funksiyanın nə etməli olduğu barədə razılaşsa da, Əməllərin təmsil edilməsi üsulları çox fərqlidir. Rust, Bir funksiyanı çağırmanın nəticələri və onun etməyə icazə verilən şeylər də fərqlidir. Rust APIs başqa dildən və ya fərqli bir ev sahibliyi mühitindən zəng edilməsinə ehtiyac Iroha xarici funksiya interfeysindən istifadə edir (FFI) oyun sahələrini bərabərləşdirmək üçün.
Bu gün istifadə olunan əsas standart C tətbiqi ikitərəfli interfeysidir. Bu sadədir, geniş yayılmış və sabitdir. Əsasən hər şeyi əl ilə edə bilərsiniz, lakin Iroha mövcud olan Rust API funksiyasından FFI uyğun funksiyaları istehsal etmək üçün iroha_ffi qabını təmin edir.
Təbii ki, bunu öz yolunuzla edə bilərsiniz. iroha_ffi qutusu hər halda istehsal etməli olduğunuz kod yaratır. Lazım olan qaynağı yazmaq kifayət qədər səylər və intizam tələb edir. FFI sərhədindən keçən hər bir funksiya çağırışı qeyri-müəyyən davranışlara səbəb ola biləcək unsafedir. Onu həll etməyi bacardığımız üsul güclü repr(C) növlərindən istifadə etmək ətrafında fırlanır.
INFO
Null yoxlaması və etibarlılığı qlobal səviyyədə tətbiq edilə bilməz, buna görə də xam göstərici (hər zaman olduğu kimi) yalnız istisna hallarda istifadə olunur. Iroha məlumat modelindəki obyektin demək olar ki, hər bir nümunəsinin ətrafında qovluqlar təqdim etdiyimizi nəzərə alaraq, ümumiyyətlə xam göstəricilərdən istifadə etmək lazım deyil.
Misal
Burada bir bağlanma yaratma nümunəsi var:
#[derive(FfiType)]
struct DaysSinceEquinox(u32);
#[ffi_export]
impl DaysSinceEquinox {
pub fn update_value(&mut self, a: &u8) {
self.0 = *a as u32;
}
}Yuxarıda göstərilən nümunədə DaysSinceEquinox ilə aşağıdakı bağlanma əmələ gətirəcəkdir.
pub extern fn DaysSinceEquinox__update_value(handle: *mut DaysSinceEquinox, a: *const u8) -> FfiReturn {
// function implementation
}FFI Bağlayıcı nəsil
FFI vasitəsilə zəng edilə bilən funksiyaları yaratmaq üçün iroha_ffi qutusu istifadə olunur. Rust strukturlarını və üsullarını nəzərə alaraq, birləşmə sərhədini keçmək üçün lazım olan unsafe kodunu yaradırlar.
A Rust növü güclü birinə çevrilmişdir repr(C) növü keçə bilən FFI ilə sərhəd FfiType::into_ffi. Bu da əksinə gedir: FFI ReprC növü bir Rust vasitəsi ilə FfiType::try_from_ffi.
WARNING
Qeyd edək ki, əks dönüşüm səhvə yol aça bilər və müəyyən edilməmiş davranışlara səbəb ola bilər. Ən açıq səhvlərdən qaçınmaq üçün əlimizdən gələni etsək də, proqramın düzgün olduğundan əmin olmalısınız.
Bağlanma istehsalını təmin edən əsas xüsusiyyətlər ReprC, FfiType və FfiConvertdir.
| Xüsusiyyət | Təsviri |
|---|---|
ReprC | Bu xüsusiyyət C-yə uyğun güclü bir tipdir. ABI. Tip təhlükəsiz bir şəkildə bölüşdürülə bilər FFI sərhədlər. |
FfiType | Bu xüsusiyyət müəyyən edilmiş Rust tipli üçün müvafiq ReprC növünü təyin edir. Təsdiqlənmiş ReprC tipi istehsal olunan FFI funksiyasının API ində Rust tipin yerinə istifadə olunur. |
FfiConvert | Bu xüsusiyyət into_ffi və try_from_ffi növünün Rust tipinə və ya ReprC tipinə çevrilməsi üçün istifadə olunan iki üsul müəyyənləşdirir. |
Qeyd edək ki, FFI üzərində mülkiyyətin ötürülməsi qeyri-müəyyən göstərici növləri istisna olmaqla yoxdur. Vec<T> kimi mülkiyyəti olan bütün digər növlər klonlaşdırılır.
Adı Mangling
FFI obyektlərinin yaradılmış adlarında ikiqat altyazıların istifadəsinə diqqət yetirin:
StructNamestrukturunda müəyyən edilmişinherent_fnmetodu üçün FFI adıStructName__inherent_fnolacaqdır.StructNamestrukturundakıTraitNamexüsusiyyətindən olanMethodNamemetodu üçün FFI adıStructNameTraitNameMethodNameolacaq.StructNamestrukturundafield_namesahəsinin təyin edilməsi üçün FFI funksiyasının adıStructName__set_field_nameolacaq.StructNamestrukturundafield_namesahəsini əldə etmək üçün FFI funksiyasının adıStructName__field_nameolacaqdır.StructNamestrukturunda dəyişənfield_namesahəsini əldə etmək üçün, FFI funksiyasının adıStrucuName__field_name_mutolacaq.Müstəqil
module_name::fn_nameüçün FFI adımodule_name::__fn_nameolacaq.Ümumi olmayan və tətbiqini bölüşməyə imkan verən xüsusiyyətlər üçün FFI (aşağıda
Clonebax) FFI adımodule_name::__cloneolacaq.rustimpl Clone for Type1 { fn clone(&self) -> Self; } impl Clone for Type2 { fn clone(&self) -> Self; }