Skip to content

Data across the boundary

Level: 301 · deep dive

Stub — an outline, not a lesson. There is no runnable example behind this page yet, so nothing on it has been through the check that backs every other claim in this library. The bullets below are the questions the finished page has to answer.

One line: A call crosses the boundary for free, but data does not — every value needs a layout both sides agree on and an owner both sides agree on, and the rule that prevents most FFI memory bugs is that whoever allocated a value is the one who frees it.

What it has to cover

  • Primitives: c_int, c_long and friends from core::ffi instead of guessing widths, and bool, char and usize as the three that surprise people
  • Strings: a Rust &str carries a length and no terminator, a C string the reverse. CStr ↗ for borrowing a C string, CString for lending one, the c"..." literal, and the encoding question — C's bytes are not promised to be UTF-8
  • Structs: #[repr(C)] layout, padding, and a struct C can see into against an opaque one it only holds a pointer to
  • Collections: a slice as a pointer and a length, and why a Vec cannot be handed over as it stands
  • Ownership: Box::into_raw to give a value to C and Box::from_raw in a matching _free function to take it back — and why C's free on Rust's allocation is undefined behaviour even when it seems to work
  • Borrowed data: a pointer C may keep only for the duration of a call, and how to say that in the header
  • The other direction: a char * from C's strdup is freed with C's free, never CString::from_raw, whose docs warn that taking ownership of a string allocated by foreign code is likely undefined behaviour; and from_raw twice on one pointer is a double free
  • API shapes that settle ownership before any code is written: the caller passes a buffer and its length, every function that returns memory has a matching _free, or the value lives behind a handle only the library creates and destroys — and callbacks across FFI for the user-data pointer C keeps

The trap it exists for

Freeing across the boundary. free() on a pointer that came from a Rust Box, or dropping in Rust what C's malloc produced, mixes two allocators; on some platforms it runs for months before it corrupts the heap.

See also

Po polsku

Samo wywołanie przez granicę C–Rust nic nie kosztuje, ale dane już tak: każda wartość potrzebuje układu w pamięci, na który zgadzają się obie strony, i właściciela, na którego też się zgadzają. Zasada, która zapobiega większości błędów pamięci w FFI, brzmi: kto zaalokował, ten zwalnia. &str w Ruscie ma długość i nie ma terminatora, łańcuch w C — odwrotnie, dlatego istnieją CStr i CString.

Szukaj po polsku: przekazywanie danych przez FFI · łańcuchy znaków C w Ruscie · rust cstr cstring ffi · rust box into_raw from_raw ffi