Interoperability between Rust and C code is always dependent on transforming data between the two languages. For this purposes there are two dedicated modules in the stdlib called std::ffi and std::os::raw.
std::os::raw deals with low-level primitive types that can be converted implicitly by the compiler because the memory layout between Rust and C is similar enough or the same.
std::ffi provides some utility for converting more complex types such as Strings, mapping both &str and String to C-types that are easier and safer to handle.
For #![no_std] environments, there is also core::raw that covers all the primitive types.
| Rust type | Intermediate | C type |
|---|---|---|
| String | CString | *char |
| &str | CStr | *const char |
| () | c_void | void |
| u32 or u64 | c_uint | unsigned int |
| etc | ... | ... |
As mentioned above, primitive types can be converted by the compiler implicitly.
unsafe fn foo(num: u32) { let c_num: c_uint = num; let r_num: u32 = c_num; }