0Pricing
Learn Rust Coding · บทเรียน

อินเทอร์เฟซฟังก์ชันภายนอก (FFI)

เรียนรู้การเรียกใช้ไลบรารี C จาก Rust และเปิดให้ภาษาอื่นเรียกใช้ฟังก์ชัน Rust ผ่าน FFI เพื่อการทำงานร่วมกันระหว่างภาษา

อินเทอร์เฟซฟังก์ชันภายนอก (FFI) เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 3 บทเรียน

FFI คืออะไร

FFI ย่อมาจาก Foreign Function Interface ซึ่งเป็นวิธีที่ช่วยให้โปรแกรมที่เขียนด้วยภาษาหนึ่งสามารถเรียกใช้ฟังก์ชันหรือโครงสร้างข้อมูลที่กำหนดไว้ในอีกภาษาได้

ใน Rust นั้น FFI ช่วยให้คุณโต้ตอบกับโค้ดที่เขียนด้วยภาษาอื่น โดยมักใช้กับภาษา C ซึ่งมีประโยชน์อย่างยิ่งเมื่อต้องผสานการทำงานกับไลบรารีที่มีอยู่แล้วหรือ API ของระบบ

เหตุผลที่ควรใช้ FFI

FFI ไม่ใช่เครื่องมือที่ต้องใช้ในชีวิตประจำวัน แต่มีประสิทธิภาพมากเมื่อคุณต้องการ:

  • ใช้ประโยชน์จากไลบรารี C ที่มีอยู่แล้ว: ไลบรารีประสิทธิภาพสูงและผ่านการพัฒนามาอย่างดีจำนวนมากเขียนด้วย C/C++ FFI ช่วยให้ Rust ใช้งานไลบรารีเหล่านี้ได้โดยตรง
  • API ของระบบ: โต้ตอบกับความสามารถของระบบปฏิบัติการที่อาจมีเฉพาะอินเทอร์เฟซของ 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);
}

การเปิดให้ C เรียกใช้ Rust: พื้นฐาน

หากต้องการทำให้ฟังก์ชัน 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

มาทดสอบความเข้าใจของคุณเกี่ยวกับ Foreign Function Interface ของ Rust กัน

FFI: สะพานเชื่อมระหว่างโลก

คุณได้เรียนรู้เกี่ยวกับ Foreign Function Interface ของ Rust แล้ว

FFI ทำให้ Rust สามารถทำงานร่วมกับภาษาอื่นได้อย่างมีประสิทธิภาพ โดยช่วยให้คุณสามารถ:

  • เรียกใช้ฟังก์ชันจากไลบรารี C ด้วย extern "C" และบล็อก unsafe
  • เปิดให้ภาษาอื่นเรียกใช้ฟังก์ชัน Rust ด้วย #[no_mangle] และ pub extern "C"
  • จัดการการจับคู่ชนิดข้อมูลอย่างรอบคอบด้วยชนิดข้อมูลใน std::os::raw

FFI เป็นเครื่องมือทรงพลังสำหรับผสาน Rust เข้ากับระบบนิเวศที่หลากหลาย แต่โปรดระลึกถึงความสำคัญของการใช้งานอย่างรอบคอบ โดยเฉพาะเรื่องความปลอดภัยและการจัดการหน่วยความจำ

คำถามที่พบบ่อย

บทเรียน “อินเทอร์เฟซฟังก์ชันภายนอก (FFI)” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “อินเทอร์เฟซฟังก์ชันภายนอก (FFI)” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 3 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “อินเทอร์เฟซฟังก์ชันภายนอก (FFI)”

เรียนรู้การเรียกใช้ไลบรารี C จาก Rust และเปิดให้ภาษาอื่นเรียกใช้ฟังก์ชัน Rust ผ่าน FFI เพื่อการทำงานร่วมกันระหว่างภาษา คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 3 บทเรียน

บทเรียน “อินเทอร์เฟซฟังก์ชันภายนอก (FFI)” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม

ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. อินเทอร์เฟซฟังก์ชันภายนอก (FFI)
  2. Rust สู่ WebAssembly (WASM)
  3. การวัดประสิทธิภาพและการปรับแต่งประสิทธิภาพ
← กลับไปที่ Learn Rust Coding