Contrary to popular belief, you can call variables / vararg functions that were defined in C. This does not mean that it is very simple, and it is definitely easier to do something bad, because there are even fewer types for the compiler to check your work.
Here is an example call to printf . I am hardcoded about almost everything:
extern crate libc; fn my_thing() { unsafe { libc::printf(b"Hello, %s (%d)\0".as_ptr() as *const i8, b"world\0".as_ptr(), 42i32); } } fn main() { my_thing() }
Note that I must make it very clear that my lines and formatting arguments are the correct types, and the lines have a NUL termination.
You will usually use tools like CString :
extern crate libc; use std::ffi::CString; fn my_thing(name: &str, number: i32) { let fmt = CString::new("Hello, %s (%d)").expect("Invalid format string"); let name = CString::new(name).expect("Invalid name"); unsafe { libc::printf(fmt.as_ptr(), name.as_ptr(), number); } } fn main() { my_thing("world", 42) }
The Rust compiler test suite also has an example of calling a variational function .
A word of warning specifically for printf functions: C-realist compilers realized that people click this type of variational function every time. To deal with this, they coded a special logic that parses the format string and tries to check the types of arguments for the types expected in the format. The Rust compiler will not check your C format strings for you!
source share