FFI (Foreign Function Interface): Rust กับ C/C++

Sharing is caring!

หนึ่งในความสามารถที่ทรงพลังของ Rust คือการติดต่อกับภาษาอื่นผ่าน FFI (Foreign Function Interface) โดยเฉพาะ C/C++ ซึ่งเป็นพื้นฐานของระบบจำนวนมาก

การทำ FFI ช่วยให้คุณสามารถ:

  • เรียกใช้ไลบรารี C/C++ จากโค้ด Rust
  • ให้ Rust ทำหน้าที่เป็นไลบรารีให้ C/C++
  • ทำงานร่วมกับ native library เช่น OpenSSL, SQLite, หรือระบบ low-level

พื้นฐานของ FFI

FFI ใน Rust ต้องใช้ unsafe เสมอ เพราะ compiler ไม่สามารถตรวจสอบ safety ของโค้ดข้ามภาษาได้

extern "C" {
    fn abs(input: i32) -> i32;
}

fn main() {
    unsafe {
        println!("abs(-10) = {}", abs(-10));
    }
}

คำสั่ง extern "C" ระบุ ABI (Application Binary Interface) แบบ C

เชื่อม Rust กับ C

1. เขียนฟังก์ชัน C

// libmath.c
int double_input(int x) {
    return x * 2;
}
// header file: libmath.h
int double_input(int x);

2. สร้าง shared object

“`bash
gcc -c -fPIC libmath.c -o libmath.o
gcc -shared -o libmath.so libmath.o

3. เขียน Rust เรียก C

 // main.rs extern "C" { fn double_input(x: i32) -> i32; } fn main() { unsafe { let result = double_input(5); println!("Result from C: {}", result); } } 

4. เพิ่ม Rust build script (optional)

toml

Cargo.toml

[dependencies]

[build-dependencies]
cc = “1.0”

 // build.rs fn main() { println!("cargo:rustc-link-lib=dylib=math"); println!("cargo:rustc-link-search=native=."); } 

Expose Rust ให้ C ใช้

 #[no_mangle] pub extern "C" fn triple_input(x: i32) -> i32 { x * 3 } 

ฟังก์ชันที่ export ออกไปต้องมี #[no_mangle] เพื่อป้องกันการเปลี่ยนชื่อสัญลักษณ์

Rust กับ C Struct

 // mystruct.h typedef struct { int x; int y; } Point; 
 #[repr(C)] pub struct Point { pub x: i32, pub y: i32, } 

การใช้ #[repr(C)] ทำให้ Rust เรียง memory layout เหมือน C

เรียก C++ จาก Rust

Rust ไม่รองรับ ABI ของ C++ โดยตรง แต่สามารถใช้ bridge ผ่าน extern “C” หรือใช้เครื่องมือเช่น cxx, bindgen

ใช้ crate cxx

 // Rust #[cxx::bridge] mod ffi { extern "C++" { include!("calc.hpp"); fn multiply(a: i32, b: i32) -> i32; } } 

แล้วให้เขียน C++ ฝั่งหนึ่งและใช้ build.rs เชื่อม

การจัดการ Memory ระหว่างภาษา

  • ต้องชัดเจนว่าใคร allocate และใคร free
  • ห้าม free จาก Rust ถ้า allocate จาก C โดยไม่เข้าใจ layout

ปลอดภัยสุดคือ copy ข้อมูลข้าม boundary แล้ว free ในที่ของตัวเอง

การใช้ bindgen

bindgen ใช้ generate Rust binding จาก header file C อัตโนมัติ
#bash
cargo install bindgen
bindgen wrapper.h -o src/bindings.rs

ข้อดีของ FFI

  • Reuse code C/C++ เดิมได้
  • เชื่อมกับ native library ได้ง่าย
  • ใช้ Rust เพื่อเขียน core logic แล้ว expose ไปยังภาษาอื่น

ข้อเสีย

  • ไม่ปลอดภัย (ต้องใช้ unsafe)
  • debug ยากขึ้น
  • มีค่าใช้จ่ายทางด้าน performance และ ABI mismatch ได้

บทสรุป

FFI เป็นสะพานเชื่อมระหว่าง Rust และโลกของภาษาอื่น โดยเฉพาะ C/C++

หากคุณต้องการทำงานกับระบบที่มีไลบรารีเก่า หรืออยาก optimize บางส่วนด้วย Rust แล้วเรียกจากภาษาอื่น — FFI คือคำตอบ

แต่จงระวัง: คุณต้องมีความรู้ทั้งสองฝั่ง และควบคุม memory ให้แม่นยำ เพราะ compiler จะไม่ช่วยคุณอีกต่อไป

เรียนรู้ FFI อย่างลึกซึ้ง แล้ว Rust จะกลายเป็นอาวุธระดับโลกของคุณ

Leave a Reply

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *