Skip to content

Гадаад үйл ажиллагааны интерфейс (FFI)

Үндсэн хуулийн iroha_ffi C үйлдвэрлэлийн макро болон шинж чанарууд нь C ABI Нүүр хуудас Rust APIs. Энэ нь Iroha төрлүүд нь дамжин FFI хязгаар, жишээ нь: SDK холболт эсвэл халамжийн нэгтгэл.

Яагаад FFI

Хөдөлмөр нь харьцангуй ухамсарсан нэгж бөгөөд ихэнх хэл функцын юу хийх ёстой талаар санал нэг байдаг ч, Хөдөлмөрийг илэрхийлэх арга нь маш ялгаатай байдаг. Rust, функцыг дуудах үр дагавар, түүний хийх зөвшөөрөлтэй зүйлүүд ч ялгаатай байдаг. Rust APIs өөр хэлээс эсвэл бусад хүлээн авч буй орчныгсаа дуудлага авах шаардлагатай. Iroha гадаад функцын интерфейс ашигладаг (FFI) өрсөлдөх нөхцөлийг тэгш болгох.

Өнөөдрийн хэрэглэгддэг үндсэн стандарт нь C аппликацын бинар интерфейс юм. Энэ нь энгийн, өргөн хүрээнд хүртээмжтэй, тогтвортой юм. Принципийн хувьд та бүх зүйлийг гараар хийж болно, гэхдээ Iroha бол FFI-ийн нийцсэн функцыг бий байгаа Rust API -ээс үүсгэх iroha_ffi хайрцаг бүрдүүлжээ.

Мэдээжийн хэрэг, та өөрийн гэсэн аргаар хийж болно. iroha_ffi crate нь зүгээр л та ямар ч тохиолдолд үүсгэх хэрэгтэй код бий болгодог. Шаардлагатай бөмбөрцгийг бичихийн тулд маш их хичээл зүтгэл, сахилга шаарддаг. FFI хязгаар нь unsafe тодорхойгүй заншил үүсгэх боломжтой. Энэ асуудлыг шийдэх арга зам нь repr(C) Ард түмэн.

INFO

Зөвхөн нөөц үзүүлэгчид л ялгаатай. null шалгалт болон хүчин төгөлдөр байдлыг дэлхий даяар хэрэгжүүлэх боломжгүй тул түүхий эд нөөцийг (хүнтэй болгон) зөвхөн онцгой тохиолдолд ашигладаг байна. Iroha мэдээллийн загварын объектын бараг бүх үлгэрлэгийг хүргэж байгаа тул та түүхий эдийг ашиглах шаардлагагүй.

Жишээлбэл

Энэ нь холболт үүсгэх жишээ:

rust
#[derive(FfiType)]
struct DaysSinceEquinox(u32);

#[ffi_export]
impl DaysSinceEquinox {
    pub fn update_value(&mut self, a: &u8) {
        self.0 = *a as u32;
    }
}

Дээр дурдсан жишээ нь DaysSinceEquinox -ийн дараах холболт үүсгэдэг бөгөөд энэ нь ил тод үзүүлэлт юм:

rust
pub extern fn DaysSinceEquinox__update_value(handle: *mut DaysSinceEquinox, a: *const u8) -> FfiReturn {
    // function implementation
}

FFI Байгууллагатай нас

iroha_ffi хайрцаг нь FFI дамжуулан дуудлагдах функцыудыг үүсгэхэд ашиглагддаг. Rust бүтэцүүд болон аргачлалуудыг харгалзан, тэд холбооны хязгаарыг дамжуулахын тулд танд шаардлагатай unsafe код бий болгоно.

Rust хэлбэрийг repr(C) хэлбэрээр өөрчилж, FFI хязгаарыг FfiType::into_ffi -тэй давтаж болно. Энэ нь эсрэгээрээ ч явагддаг: FFI ReprC хэлбэрийг Rust хэлбэрээр FfiType::try_from_ffi дамжуулан өөрчлөх боломжтой.

WARNING

Харин эсрэг хэлбэр нь алдаатай бөгөөд тодорхойгүй зан үйл үүсгэх боломжтой гэдгийг анхаараарай. Бид хамгийн ил тод алдаанаас зайлсхийхийн тулд чадах бүхнээ хийж чаддаг хэдий ч та програмын зөв байдлыг хангах ёстой.

Төгсэл үүсгэх боломжийг олгодог үндсэн шинж чанар нь ReprC, FfiType, FfiConvert.

Үргэлж .Тодруулга
ReprCЭнэ шинж чанар нь C ABI -д нийцсэн хүчтэй хэлбэр юм. Тус хэлбэрийг FFI -ийн хилүүдэд аюулгүй хуваалцах боломжтой.
FfiTypeЭнэ шинж чанар нь тухайн Rust төрөлд хамааралтай ReprC хэлбэрийг тодорхойлдог. үүссэн FFI функцын API функцинд Rust хэлбэрийн оронд тодорхойлсон ReprC хэлбэр ашиглагддаг.
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.

    rust
    impl Clone for Type1 {
        fn clone(&self) -> Self;
    }
    impl Clone for Type2 {
        fn clone(&self) -> Self;
    }