Шетелдік функция интерфейстері (FFI)
Қауымдастық iroha_ffi коробка C өндірісі үшін макролар мен қасиеттерді ұсынады ABI байланыстар Rust APIs. Бұл жерде қолданылады: Iroha түрлер арқылы өту керек FFI шекарасы, мысалы SDK байланыстар немесе қоректендіру интеграциялары.
Неге FFI
Функция - бұл абстрактты бірлік. Көптеген тілдер функцияның не істеу керектігі туралы келісе отырып, Сонымен қатар, кейбір тілдерде, мысалы: Rust, Функцияны шақырудың салдары және оған рұқсат етілген нәрселер де әртүрлі. Rust APIs басқа тілден немесе басқа қонақ ортадан шақыру қажет, Iroha сыртқы функция интерфейсін пайдаланады (FFI) ойын шарттарын теңестіру.
Бүгінгі таңда қолданылатын негізгі стандарт - C қолданбалы бинарлық интерфейс. Ол қарапайым, кеңінен қол жетімді және тұрақты. Негізінде сіз бәрін қолмен жасай аласыз, бірақ Iroha қолданыстағы Rust API функцияларынан FFI-қа сәйкес функцияларды тудыру үшін iroha_ffi қорын ұсынады.
iroha_ffi коды тек сізге қажет кодты ғана шығарады. Қажетті қазандықтарды жазу үшін біраз қамқорлық пен тәртіп қажет. FFI шегінен өткен әрбір функцияның шақыруы unsafe болып табылады, ол анықталмаған мінез-құлқын тудыруға мүмкіндік береді. Біз оны шешуді атқарған әдіс берік repr(C) типтерін қолдану арқылы айналады.
INFO
Бірден-бір ерекшелік - көрсеткіштері. Нөлдік тексеру мен жарамдылық жалпыға бірдей қолданылмайды, сондықтан сырьелі көрсеткіштер (әдеттегідей) тек ерекше жағдайларда қолданылады. Біз Iroha деректер моделіндегі нысанның кез-келген үлгісіне қаптамалар ұсынатындықтан, сіз шикі көрсеткіштерді қолданбауыңыз керек.
Мисал
Мұнда бұзылуды құрудың мысалы келтірілген:
#[derive(FfiType)]
struct DaysSinceEquinox(u32);
#[ffi_export]
impl DaysSinceEquinox {
pub fn update_value(&mut self, a: &u8) {
self.0 = *a as u32;
}
}Жоғарыда келтірілген мысал DaysSinceEquinox арқылы ашық емес көрсеткіш ретінде көрсетілген келесі байланысты туғызады:
pub extern fn DaysSinceEquinox__update_value(handle: *mut DaysSinceEquinox, a: *const u8) -> FfiReturn {
// function implementation
}FFI Байланысты ұрпақ
iroha_ffi коробкасы FFI арқылы шақырылатын функцияларды туғызу үшін қолданылады. Rust құрылымы мен әдістерін ескере отырып, олар байланыстыру шекарасын кесіп өту үшін қажет болатын unsafe кодты туғызады.
Rust үлгісі берік repr(C) түріне айналады, ол FfiType::into_ffi арқылы FFI шекарасын аша алады. Бұл керісінше де болады: FFI ReprC түрі Rust түріне FfiType::try_from_ffi арқылы айналады.
WARNING
Кері айналымның қате екенін және анықталмаған мінез-құлықтарға әкелуі мүмкін екенін ескеріңіз. Біз ең анық қателерді болдырмау үшін барынша күш сала аламыз, бірақ сіз бағдарламаның дұрыстығын қамтамасыз етуіңіз керек.
Байланыс туындысын құруға мүмкіндік беретін негізгі белгілер - ReprC, FfiType және FfiConvert.
| қасиеттер | Бейнелеу |
|---|---|
ReprC | Бұл қасиет C ABI сәйкес келетін берік типті білдіреді. Тип FFI шекараларында қауіпсіз бөлінеді. |
FfiType | Бұл белгі белгілі бір Rust тип үшін тиісті ReprC түрін анықтайды. Белгіленген ReprC түрі Rust түрінің орнына пайда болған FFI функциясының API құрамында қолданылады. |
FfiConvert | Бұл сипаттама into_ffi және try_from_ffi түрін Rust түріне немесе ReprC түрінен қайтару үшін қолданылатын екі әдісті анықтайды. |
Байқаңыз, оған иелік етудің берілуі жоқ FFI Өткінші индикатор түрлерін қоспағанда, басқа да меншік иелері бар типтер: Vec<T>, клондалған.
Атын Манглинг
FFI нысандарының генериленген атауларында қос қосалқы белгілер қолданылуын ескеріңіз:
StructNameқұрылымында айқындалғанinherent_fnәдісі үшін FFI атауыStructName__inherent_fnболып табылады.StructNameконструкциясындағыTraitNameбелгісінен алынғанMethodNameәдісі үшін FFI атауыStructNameTraitNameMethodNameболады.StructNameқұрылымындаfield_nameөрісін орнату үшін FFI функциясының атауыStructName__set_field_nameболып табылады.StructNameқұрылымындағыfield_nameөрісін алу үшін FFI функциясының атауыStructName__field_nameболады.StructNameқұрылымындағы өзгеріске қабілеттіfield_nameөрісін алу үшін FFI функциясының атауыStrucuName__field_name_mutболады.Үзіліссіз
module_name::fn_nameүшін FFI атауыmodule_name::__fn_nameболады.FFI (бұдан әрі -
Cloneқараңыз) жалпы емес және оларды іске асыруды ортақтастыруға мүмкіндік беретін белгілер үшін FFI атауыmodule_name::__cloneболады.rustimpl Clone for Type1 { fn clone(&self) -> Self; } impl Clone for Type2 { fn clone(&self) -> Self; }