Learn Rust Coding · درس

واجهة الدوال الأجنبية (FFI)

تعلّموا استدعاء مكتبات C من Rust وإتاحة دوال Rust للغات أخرى باستخدام FFI لتحقيق التشغيل البيني.

الدرس 1 من 311 خطوة

واجهة الدوال الأجنبية (FFI) درس مجاني في Learn Rust Coding على CoddyKit. هذا هو الدرس 1 من أصل 3. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Learn Rust Coding، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Learn Rust Coding 3 دروس في المجموع.

ما هي FFI؟

اختصار FFI يعني واجهة الدوال الأجنبية (Foreign Function Interface). وهي وسيلة تتيح للبرامج المكتوبة بلغة برمجة ما استدعاء دوال أو استخدام هياكل بيانات معرّفة في لغة أخرى.

تتيح FFI في Rust التفاعل مع تعليمات برمجية مكتوبة بلغات أخرى، وأكثرها شيوعًا C. وهذا مفيد جدًا للدمج مع المكتبات الحالية أو واجهات برمجة تطبيقات النظام.

لماذا نستخدم FFI؟

ليست FFI أداة تُستخدم يوميًا، لكنها قوية عندما تحتاجون إلى ما يلي:

  • الاستفادة من مكتبات C الحالية: كُتبت كثير من المكتبات الناضجة وعالية الأداء بلغة C/C++. وتتيح FFI لـ Rust استخدامها مباشرةً.
  • واجهات برمجة تطبيقات النظام: التفاعل مع ميزات نظام التشغيل التي قد لا توفر إلا واجهات C.
  • التوافقية: بناء مكتبة Rust يمكن استدعاؤها من لغات أخرى (مثل Python أو Java أو JavaScript عبر Node.js).

استدعاء C من Rust: التصريح

لاستدعاء دالة C من Rust، تحتاجون أولًا إلى التصريح عن توقيعها باستخدام كتلة extern "C". ويُخبر هذا Rust بشكل دالة C من دون توفير تنفيذها.

يحدد الجزء "C" اصطلاح استدعاء C، مما يضمن توافق استدعاءات الدوال.

extern "C" {
    // Declare C functions here
    // Example: int puts(const char *s);
    fn puts(s: *const std::os::raw::c_char) -> std::os::raw::c_int;
    // Example: int add(int a, int b);
    fn add(a: std::os::raw::c_int, b: std::os::raw::c_int) -> std::os::raw::c_int;
}

استدعاء C من Rust: كتلة `unsafe`

الوعد الأساسي لـ Rust هو أمان الذاكرة. لكن عند التفاعل مع تعليمات برمجية بلغة C عبر FFI، لا تستطيع Rust ضمان أمان التعليمات البرمجية الأجنبية.

لذلك، يجب تضمين أي استدعاء لدالة C مُعلنة في كتلة extern "C" داخل كتلة unsafe. وهذا يشير إلى المترجم (والمطورين الآخرين) إلى أنكم مسؤولون عن الحفاظ على ضمانات الأمان.

extern "C" {
    // We're declaring that a C function `puts` exists.
    fn puts(s: *const std::os::raw::c_char) -> std::os::raw::c_int;
}

fn main() {
    let rust_string = "Hello from Rust via C!";
    // C strings need to be null-terminated.
    let c_string = std::ffi::CString::new(rust_string).expect("CString failed");

    unsafe {
        // Calling the C 'puts' function. This requires 'unsafe'.
        puts(c_string.as_ptr());
    }
    println!("C function call demonstrated.");
}

مطابقة الأنواع: من Rust إلى C

عند استخدام FFI، يجب التأكد من أن أنواع Rust تطابق أنواع C بشكل صحيح. توفر Rust أنواعًا محددة في std::os::raw وstd::ffi لهذا الغرض.

  • i32 -> std::os::raw::c_int
  • f32 -> std::os::raw::c_float
  • bool -> std::os::raw::c_uchar (أو نوع مشابه، إذ لا تملك C نوعًا منطقيًا قياسيًا)
  • &str -> *const std::os::raw::c_char (تحتاج سلاسل C إلى إنهاء صفري، وغالبًا ما يتولى std::ffi::CString ذلك)
  • &mut [T] -> *mut T

استخدموا دائمًا أنواع C الصريحة هذه لتجنب السلوك غير المحدد.

مثال: استدعاء دالة C باسم `add`

لنفترض أن لدينا مكتبة C تحتوي على الدالة int add(int a, int b);. إليكم كيفية استدعائها من Rust. لاحظوا استخدام c_int لأنواع الأعداد الصحيحة.

(يوضح هذا الرمز بنية FFI، لكنه لن يعمل من دون مكتبة C مُصرّفة ومرتبطة خارجيًا.)

extern "C" {
    // Declaration of the C function `add`
    fn add(a: std::os::raw::c_int, b: std::os::raw::c_int) -> std::os::raw::c_int;
}

fn main() {
    let x = 10;
    let y = 20;

    let result = unsafe {
        // Call the C 'add' function within an unsafe block
        add(x as std::os::raw::c_int, y as std::os::raw::c_int)
    };

    println!("Attempted to call C add. Result (if linked): {}", result);
}

إتاحة Rust لـ C: الأساسيات

لجعل دالة Rust قابلة للاستدعاء من C، تحتاجون إلى أمرين:

  1. #[no_mangle]: تمنع هذه السمة مترجم Rust من «تشويه» (تغيير) اسم الدالة. إذ تتوقع مترجمات C أسماء بسيطة غير مشوهة.
  2. extern "C": يحدد هذا أن الدالة يجب أن تستخدم اصطلاح استدعاء C، مما يجعلها متوافقة مع C.

مثال: دالة Rust لصالح C

إليكم دالة Rust تحسب مجموعًا ويمكن استدعاؤها من برنامج C. لاحظوا سمتي #[no_mangle] وextern "C".

(صُممت هذه التعليمات البرمجية ليتم تجميعها كمكتبة لصالح C، لكنها تتضمن main للاختبار الداخلي ضمن هذه البيئة.)

#[no_mangle]
pub extern "C" fn rust_add_and_print(
    a: std::os::raw::c_int,
    b: std::os::raw::c_int
) -> std::os::raw::c_int {
    let sum = a + b;
    println!("Rust function received: {} + {} = {}", a, b, sum);
    sum
}

fn main() {
    println!("This Rust code exposes a function for C.");
    // We can also call it internally for demonstration
    let result = rust_add_and_print(5, 7);
    println!("Internal call result: {}", result);
}

إدارة الذاكرة في FFI

تُعد إدارة الذاكرة عبر حدود FFI أمرًا بالغ الأهمية. فإذا خصصت Rust ذاكرة (مثل سلسلة نصية) ومررت مؤشرًا إلى C، فيجب على C إما نسخ البيانات أو تولي مسؤولية تحريرها بشكل صحيح.

وبالعكس، إذا خصصت C الذاكرة ومررت مؤشرًا إلى Rust، فلا ينبغي لـ Rust تحريرها ما لم يُطلب منها ذلك صراحةً، أو يجب عليها نسخ البيانات.

تساعد أدوات مثل std::ffi::CString وCStr على إدارة السلاسل المتوافقة مع C بأمان، من خلال التعامل مع الإنهاء الصفري وضمان نقل الملكية بشكل صحيح.

اختبار سريع حول FFI

لنختبر مدى فهمكم لواجهة الدوال الأجنبية في Rust.

FFI: جسر بين عالمين

لقد تعلّمتم عن واجهة الدوال الأجنبية في Rust!

تتيح FFI لـ Rust أن تكون أداة قوية حقيقية للتوافقية، إذ تمكّنكم من:

  • استدعاء الدوال من مكتبات C باستخدام extern "C" وكتل unsafe.
  • إتاحة دوال Rust للغات أخرى باستخدام #[no_mangle] وpub extern "C".
  • التعامل بحذر مع مطابقة الأنواع باستخدام أنواع std::os::raw.

تُعد FFI أداة قوية لدمج Rust في منظومات متنوعة، لكن تذكّروا أهمية استخدامها بحذر، ولا سيما فيما يتعلق بالأمان وإدارة الذاكرة!

البدء مجانًا

تعلم Rust مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
39
الدروس
144

الأسئلة الشائعة

هل درس «واجهة الدوال الأجنبية (FFI)» مجاني؟

نعم — نص درس «واجهة الدوال الأجنبية (FFI)» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Learn Rust Coding، انتقل إلى CoddyKit PRO. تتضمن دورة Learn Rust Coding 3 دروس في المجموع.

ماذا ستتعلم في «واجهة الدوال الأجنبية (FFI)»؟

تعلّموا استدعاء مكتبات C من Rust وإتاحة دوال Rust للغات أخرى باستخدام FFI لتحقيق التشغيل البيني. تتمرن على Learn Rust Coding مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Learn Rust Coding؟

لا تُشترط خبرة سابقة. Learn Rust Coding على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 3.

كم من الوقت يستغرق درس «واجهة الدوال الأجنبية (FFI)»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Learn Rust Coding هذا؟

نعم. كل درس في Learn Rust Coding يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. واجهة الدوال الأجنبية (FFI)
  2. من Rust إلى WebAssembly (WASM)
  3. قياس الأداء وضبطه
← العودة إلى Learn Rust Coding