อินเทอร์เฟซฟังก์ชันภายนอก (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_intf32->std::os::raw::c_floatbool->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 ได้ คุณต้องมีสองสิ่งต่อไปนี้:
#[no_mangle]: แอตทริบิวต์นี้ป้องกันไม่ให้คอมไพเลอร์ของ Rust "ดัดแปลงชื่อ" (เปลี่ยนชื่อ) ฟังก์ชัน คอมไพเลอร์ C ต้องการชื่อที่เรียบง่ายและไม่ถูกดัดแปลง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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- อินเทอร์เฟซฟังก์ชันภายนอก (FFI)
- Rust สู่ WebAssembly (WASM)
- การวัดประสิทธิภาพและการปรับแต่งประสิทธิภาพ